Deploy an Apache Web Server on CentOS 6


This tutorial will guide you through deploying an Apache web server on CentOS 6. With security a top priority for public-facing web servers, I’ll show you how to do the configuration with SELinux enabled, using customized policies to ensure we’re protected at all times. Does the thought of SELinux scare you? If so, you’ll be surprised by how easy it is to actually use, when done properly.

The scope of this tutorial will be on Apache and PHP only. Databases will not be covered, as it is expected that service will be hosted on another server. This server will be ideal for either simple applications or load-balanced web farms.


  • Install and configure Apache
  • Install and configure PHP
  • Use Non-default Apache Web Directories
  • Create SELinux Policies for Web Application

Server Configuration

The lab server used has the following configuration, for those following along. It’s used for example purposes only. As each application has its own requirements, you should size your server accordingly.

Hardware Configuration

Processor 2 Cores Web Server Apache 2.2.15
RAM 1 GB Database Server MySQL Server 5.1
Hard Disk 1 x 48 GB Web Server Apache 2.2.15
Network Interfaces 1 Web Application WordPress

Storage Configuration

Mount Point File System Size Notes
MBR – Standard Partitions
/boot EXT2 200 MB The boot image is small and it doesn’t need the overhead added by EXT4’s journaling. Other than minimizing the complexity of the file system used by /boot, there are very few benefits for placing it on its own partition with a large majority of today’s Linux distros.
Mount Point Volume Group Volume Name File System Size
LVM – Logical Volumes
/ vg01 lv_root EXT4 10 GB
/home vg01 lv_home EXT4 1 GB
/var/log vg01 lv_logs EXT4 5.5 GB
/srv/webapps vg01 lv_webapps EXT4 5.5 GB
vg01 lv_swap SWAP 1.5 GB

Mount Points

We have our mount points defined, but we need to configure them in /etc/fstab with security in mind for some of them.

  1. Open fstab into a text editor, like VIM, for example.vim /etc/fstab
  2. Following along with the disk layout above, find the following lines in fstab and add the highlighted options.
    /dev/mapper/vg01-lv_home    /home     ext4    defaults,nosuid,nodev,noexec   1 2
    /dev/mapper/vg01-lv_logs     /var/log  ext4    defaults,nosuid,nodev   1 2
    /dev/mapper/vg01-lv_webapps /srv/webapps  ext4    defaults,nodev,noexec   1 2
    nodev Prevents device files from existing on the mount point’s file system. Unless you have some special requirements, device files should only exist in /dev.
    noexec Prevents executable files from running on the mount points file system. In this tutorial, we have it set for our web app mount. If your web application requires cgi, this will break the application and you should not add it.
  3. Save the modified fstab file and exit the text editor.
  4. Reboot the server or unmount and then remount the modified mount points to apply the changes.

Prepare the Server

The following steps are designed to help you prepare the server before the server for Apache and your web applications.

Creating Users and Groups

After the deployment is complete, no one should use the Root account unless absolutely required. We need to create two user accounts and two groups, one for day-to-day maintenance of the web applications and another for system administration. After we’ve created our users and groups, we’ll then secure SSH to only allow our non-administrative accounts remote access. This separation adds another layer of security to help prevent hackers from gaining complete control, if they were successfully in remotely logging in with someone’s account.

  1. Create your day-to-day user account.useradd jsmith
  2. Set your password for this accountpasswd jsmith
  3. Create your server admin account.useradd jsmith-admin
  4. Set your admin account’s passwordpasswd jsmith-admin
  5. Create your webadmins group.groupadd webadmins
  6. Create your system administrator group.groupadd sysadmins
  7. Create a remote administration group for which we’ll grant SSH access.groupadd remoteadmins
  8. Add your day-to-day account to the webadmins group.usermod -G webadmins -a jsmith
  9. Add your server admin account the system administrator group.usermod -G sysadmins -a jsmith-admin
  10. Add the Apache account to the webadmins group to grant it access to our /webapps directory, which will be needed after we secure it below.usermod -G webadmins -a apache
  11. Since we want jsmith, being us, remote access into our web server, we need to add the account to the remoteadmins group.usermod -G remoateadmins -a jsmith

Granting System Administration Rights

We’re now going to assign accounts who need system administration rights to our sysadmins group. Through sudo, the sysadmins group will have full administrative rights. Root will then be given a very complex password to protect it from misuse.

  1. Open the sudoers file editorvisudo
  2. Navigate to the bottom of the file and add the following line:
    %sysadmins     ALL=(ALL)     ALL
  3. To save our settings, press ESC and then type colon (:) and ‘w’.
  4. Type colon (:) and ‘q’ to exit the editor.
  5. Set a complex password for the Root account. The longer, more complex it is, the better.

Locking Down SSH Access

SSH is a great tool for remote administration of your Linux servers; however, left unprotected using default settings is very risky. Brute forcing into any server is a two step process: find a user account and discover the user account’s password. And what account is known to exist on every Linux server? Root. For this reason, it is best practice to prevent Root from having remote access to the server. Another concern is ‘who has access rights into the server?’ By default, SSH will grant access to all accounts. Since not every user should have the ability to SSH into the server, we want to ensure only authorized users can do so. To do this, we are going to configure SSH to only allow users in the remoteadmins group permission to remotely access the server.

  1. Open the SSH Server configuration file into a text editor, like VIM.vim /etc/ssh/sshd_config
  2. Find the line that permits Root logon#PermitRootLogin yesUncomment it by removing the hash mark ‘#’ and replacing ‘yes’ with ‘no’. Note: despite this option being commented out, by default SSH grants Root login permissions. This is why it is important we uncomment the option and explicitly set it to ‘no’.PermitRootLogin no
  3. Now, we just want authorized users to have access on our server through SSH. Add the ‘AllowGroup’ option to the configuration file, and then append the groups we want to allow access to.AllowGroups remoteadmins
  4. Save the configuration file and exit the editor.
  5. Restart the SSH daemon to apply our changes.service sshd restart

To add additional security hardening to SSH, use keys instead of passwords. Learn how by reading Passwordless SSH Logons on CentOS 6 using RSA Authentication Keys.

Prepare the Webapps Directory Structure

The default location for an Apache website on CentOS servers is /var/www/html. This is fine if you do not expect to ever add addtional web applications using Apache’s virtual hosts. Otherwise, it’s best to create your own directory structure.

Before we install Apache and start defining web sites, we need to prepare our webapps directory. Inside of the /srv/webapps directory, we’re going to create separate directories for each of our applications and their logs (see example below), starting with what we’ll call App1.

  1. Create application directorymkdir -p /srv/webapps/app1/public_html
  2. Create application log directorymkdir -p /srv/webapps/app1/logs
  3. Change /webapps group ownership to our webadmins.chgrp -Rv webadmins /srv/webapps
  4. Set the guid bit recursively for the webapps directory to ensure all new files and directories are owned by the webadmins group. Also, we’re going to grant read/write access to the webadmins group and file owners, and no access to anyone else.chmod 2770 -Rv /srv/webapps
  5. With the public_html directory, we’re going to grant read access to everyone.chmod 2775 -Rv /srv/webapps/app1/public_html

Creating SELinux Policies

Install Required Packages

Before we can create our own policies, we need to ensure SEMANAGE is installed. This application allows us to browse through the existing, default context policies, and create our own.

  1. Open a console with root privileges
  2. Install the policycoreutils-python package, which contains SEMANAGE.
    yum install -y policycoreutils-python
  3. For troubleshooting SELinux issues, download the setroubleshooting package. This step is actually optional, but you’ll be thankful for it when you are able quickly diagnose SELinux problems with it.
    yum install -y setroubleshooting

Apache Context Types

Before we can start creating our own policies for applying Apache’s context types, we need to understand which are available to us out of the box. The following table shows the ones we are primarily interested in, however there are several others available.

httpd_sys_content_t Read-only directories and files used by Apache
httpd_sys_rw_content_t Readable and writable directories and files used by Apache. Assign this to directories where files can be created or modified by your application, or assign it to files directory to allow your application to modify them.
httpd_log_t Used by Apache to generate and append to web application log files.
httpd_cache_t Assign to a directory used by Apache for caching, if you are using mod_cache.

Create the Policies

  1. Create a policy to assign the httpd_sys_content_t context to the /webapps directory, and all child directories and files.
    semanage fcontext -a http_sys_content_t "/srv/webapps(/.*)?"
  2. Create a policy to assign the httpd_log_t context to the logging directories.
    semanage fcontext -a httpd_log_t "/srv/webapps/logs(/.*)?"

Assign Policies to Application Directory

With the policies defined, it’s time to assign them to our web application directories. To do so we use the restorecon command against our webapp’s parent directory.

  1. Apply the SELinux policies
    restorecon -Rv /srv/webapps

That’s it! We’re done. I bet it was a lot easier than you expected. Too many tutorials disable SELinux, because everyone seems to be afraid. Although complicated underneath the covers, it’s actually very simplistic to administer.

Installing and Configuring Apache

Installing Apache

  1. Install Apache 2yum install httpd

Configure Apache

  1. Open Apache’s configuration file into a text editor, like VIM.vim /etc/httpd/conf/httpd.conf
  2. Prevent Apache from advertising its version by turning Server Signature off. To do so, locate the following lineServerSignature On and replace it withServerSignature Off
  3. Prevent Apache from advertising operating system info. To do so, locate the following lineServerTokens OS and replace it withServerTokens Prod
  4. Change the location of the web applications root directory from /var/www to our new location. Find the following line<Directory "/var/www/html">and replace it with<Directory "/srv/webapps/app1/public_html">
  5. Prevent directories from showing their contents in a web browser by removing the Indexes option. To do so, find the following, located just under the line we modified above.Options Indexes FollowSymLinksand replace it withOptions FollowSymLinks
  6. Change the location of the error log by locating the following lineErrorLog logs/error_logand replace it withErrorLog /srv/webapps/app1/logs/error_log
  7. Change the location of the access log by locating the following lineCustomLog logs/access_log combinedand replace it withCustomLog /srv/webapps/app1/logs/access_log combined
  8. Save the changes and exit the text editor.
  9. Add the Apache user account to our webadmins group, to grant Apache rights to our application directories.
    usermod -G webadmins -a apache
  10. Start the Apache daemon.service httpd start
  11. Configure the Apache daemon to start automatically after boot.chkconfig httpd on

Installing and Configuring PHP

Installing PHP

Although MySQL isn’t being installed on this server, if you application requires database connectivity we need to install php-mysql.

  1. Install PHP5 and extensions for MySQL.yum install php php-mysql

Configure PHP

  1. Open PHP’s configuration file into a text editor, like VIM.vim /etc/php.ini
  2. There are a few functions that should be disabled to security reasons, unless you know for sure that your web application requires them. Find the following line.disable_functions =and replace it with
    disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
  3. Find the line containing option display_errors and ensure it is set to ‘off’.display_errors = Off
  4. Find the line containing option register_globals and ensure it is set to ‘off’.register_globals = Off
  5. Find the line containing option magic_quotes_gpc and ensure it is set to ‘off’.magic_quotes_gpc = Off
  6. Save your changes and exit the text editor.
  7. Restart Apache to apply the new PHP settings.service httpd restart

Open the Firewall

Before users can access our web application through a web browser port 80 will have to be opened up. By default, IPtables – a Linux firewall service – blocks this port.

  1. Run the following command to configure IPTables through a basic GUI-like interface.system-config-firewall-tui
  2. Ensure that the firewall is enabled.
  3. Press Tab to navigate to Customize, and press Enter.
  4. Scroll down the trusted services list until you see WWW (HTTP).
  5. Enable access to it by pressing the Spacebar.
  6. Press Tab to navigate to the Close button, and press Enter.
  7. Press Tab to navigate to the OK button, and press Enter.


We now have a secured, role-specific web server. Your next step is going to be deploying a database server for your application. The benefit of using role specific servers is they are more secure and a lot easier to scale out.