Skip to Main Content

Configure a CentOS 6.4 Web Server on Rackspace - Part 4: Virtual Hosts

You'll probably want to host multiple domains on your server. To do that we will need to set up Apache virtual hosts. There is more than one way to do this. The configuration below assumes that there is one server administrator who manages multiple hosted domains. In other words, this setup is good for web developers who host their own clients and manage their client's sites.

First, change permissions on the admin user's directory:

$ sudo chmod 755 /home/admin

Create the First Hosted Domain

Create a home directory for your first hosted domain. We'll use www.mydomain1.com as an example. Note that further down when we edit the Apache settings in the httpd.conf file we'll be enforcing the www version as our canonical domain, so we need the directory name to match. If you plan to enforce the non-www version, then don't include the www in the directory name either.

$ mkdir -p /home/admin/sites/www.mydomain1.com/public_html

 Add an index.html file to the hosted domain's public folder:

$ vim /home/admin/sites/www.mydomain1.com/public_html/index.php 

And add some code to the index.php file:

<?php
    echo phpinfo();

You can repeat the steps above for each domain you want to host.

Configure Apache for Virtual Hosting

Open the Apache config file httpd.conf:

$ sudo vim /etc/httpd/conf/httpd.conf

Near the bottom of the file uncomment the line that reads:

NameVirtualHost *:80

Normally each hosted domain gets an separate entry in httpd.conf. However, this makes it cumbersome to add new domains. The following setup can be used for mass virtual hosting so that we won't need to add each new hosted domain to httpd.conf. With these settings, all we'll need to do is add a new directory to /home/admin/public_html/ for each new site we host. Pretty cool.

We'll also enforce the www version as the canonical domain here in httpd.conf because it's more efficient than using .htaccess.

<VirtualHost *:80>

  # Redirect non-www to www for all domains
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteCond %{HTTP_HOST} !^www..+$ [NC]
  RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

  # Set the home directory for each domain based
  # on the request. %0 will be the domain name.
  VirtualDocumentRoot /home/admin/sites/%0/public_html

  # Fix the broken $_SERVER_[DOCUMENT_ROOT] with this hack
  php_admin_value auto_prepend_file /home/admin/docroot.php

</VirtualHost>

Apache can run into memory problems if each virtual host has it's own log file. So what we'll do is combine the logs for all the domains into a single, common log file. The log file can be split programmatically on a per-virtualhost basis for reporting, etc.

In httpd.conf, search for LogFormat. Add the following 2 lines right after the existing entries for LogFormat:

LogFormat "%V %h %l %u %t "%r" %>s %b" vhost
CustomLog /home/admin/logs/vhost.log vhost

Save and close httpd.conf.

Logging

Create a directory to store the log files:

$ mkdir /home/admin/logs
$ touch /home/admin/logs/vhost.log
$ chmod 664 /home/admin/logs/vhost.log

Log files can get big quickly, so we need to make sure the logrotate program knows about our vhost.log file. We just need to add our new log file to the existing Apache logrotate configuration:

$ sudo vim /etc/logrotate.d/httpd

The first line of the file should look like this:

/var/log/httpd/*log {

We're going to add the path to our vhost.log file right after the existing path. Make sure there's a space separating the file paths. So your first line should now be:

/var/log/httpd/*log /home/admin/logs/vhost.log {

The next few lines of the file are a stack of commands (see this Slicehost article for more details). We'll leave them as is, but let's add one additional command right at the top of the stack:

size 10M

Now our logs will rotate every week, or when they reach 10 megabytes, whichever comes first. I would also recommend installing Logwatch to get daily email reports about the state of your server.

Finishing Up

In the last line of the VirtualHost block in httpd.conf you may have noticed a reference to a file called docroot.php. That file is a hack that is used to fix the broken DOCUMENT_ROOT that results from this mass virtual hosting configuration. With the hack in place we will be able to use $_SERVER[DOCUMENT_ROOT] in PHP and get the correct result. Create the file with $ vim /home/admin/docroot.php, then add the following contents:

<?php
    $docroot = str_replace($_SERVER['SCRIPT_NAME'], '',
    $_SERVER['SCRIPT_FILENAME']);
    $_SERVER['DOCUMENT_ROOT'] = $docroot;
    apache_setenv("DOCUMENT_ROOT", $docroot);

Finally, let's restart Apache so the new configuration takes effect:

$ sudo service httpd restart

Now we should be able to go to www.mydomain1.com and see our test page (assuming we've set up the DNS for www.mydomain1.com of course).

Additional Resource: Slicehost article on another virtual host configuration

Next > Part 5: Postfix Email Forwarding 

Configure a CentOS 6.4 Web Server on Rackspace - Part 3: Starting the Server

Firewall

First we need to enable iptables (the CentOS firewall) and open some ports to allow access from the web:

$ sudo service iptables start

Let's make sure the server always starts iptables after a reboot:

$ sudo chkconfig iptables on

Now we need to open some ports in our firewall. We'll do that using the GUI we installed:

$ sudo system-config-firewall-tui
# If it refuses to start run the command below, for this bug fix:
# https://bugzilla.redhat.com/show_bug.cgi?id=1123919
$ sudo service messagebus start 

  1. Hit the tab key to highlight the Customize button, then press enter. Use the arrow key to scroll through the list. Hit enter to enable the ports that need to be opened. A star will appear next to each service name that we've enabled. For now let's just open 3 ports:
        [*] SSH
        [*] Secure WWW (HTTPS)
        [*] WWW (HTTP)
  2. Hit the tab key again to highlight the Close button, then press enter. On the next screen select OK, then press enter.

Note: Don't open the FTP port. You should aways use SFTP, which works just like FTP but runs over the SSH port making it more secure.

Now we need to restart iptables so that our rules will take effect:

$ sudo service iptables restart

The iptables configuration file is located in /etc/sysconfig/iptables. This is the file that the GUI modified. You can modify it directly if you prefer.

Note: On Linode I ran into an error restarting iptables. If you see the error below, see this blog post for the solution.

iptables: Setting chains to policy ACCEPT: security raw nat[FAILED]filter

Fail2Ban (Requires EPEL)

Fail2Ban monitors log files looking for suspicious behavior, like too many failed login attempts. When if finds a evil IP address, it adds a rule to iptables to block that IP. If you installed the EPEL repos in the earlier section, you can install fail2ban to give your server some added protection.

$ sudo yum -y install fail2ban
$ sudo chkconfig fail2ban on
$ sudo service fail2ban start

Now we'll copy the .conf file and edit the .local version so we can tweak the settings:

$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
$ sudo vim /etc/fail2ban/jail.local 

In jail.local, look for the section beginning with [DEFAULT]. Add your IP address to the ignoreip setting (use spaces to separate multiple IPs). You can change the values of bantime and maxretry if you wish. Then restart the service:

$ sudo service fail2ban restart

You can see that fail2ban is active by checking the iptables rules.

$ sudo iptables -L

Apache

Let's get the Apache web server (known as httpd) up and running:

$ sudo service httpd start

And we'll make sure the server always starts Apache after a reboot:

$ sudo chkconfig httpd on

We can check that the above command worked by typing:

$ sudo chkconfig --list httpd
# this should output:
# httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off

MySQL 

Finally let's start MySQL:

$ sudo service mysqld start
$ sudo chkconfig mysqld on

Run the setup script:

$ sudo mysql_install_db

And security harden the installation a bit by running this next script.

$ sudo mysql_secure_installation

# Just hit enter here
Enter current password for root (enter for none):

You will then be asked to create a root MySQL password. After that, say yes to all the remaining questions (type Y at each prompt and hit enter). 

You can test your MySQL login:

$ mysql -u root -p
$ Password:

If you see a MySQL prompt, all is well. You can exit MySQL:

> exit

Visit Your Server

Open your web browser and enter your server's IP address in the address bar. You should see an Apache welcome screen, indicating that the server is up and running.

Next > Part 4: Apache Virtual Hosts

 

Configure a CentOS 6.4 Web Server on Rackspace - Part 2: Installing Packages

We'll need to install the various pieces of software. The easiest way to do that is with the yum package manager. After entering each yum command you will be asked to confirm the installation by typing the y key and pressing enter.

First, let's update the OS and any preinstalled packages. Notice we now have to use the sudo command to run system admin tasks. You will be prompted for your password when using sudo.

$ sudo yum -y update

Next, I'm going to add the Extra Packages for Enterprise Linux 6 (EPEL) repository. This is not required, but EPEL has additional packages that I want (e.g. Fail2Ban, phpMyAdmin).

$ curl -L https://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm > epel-release-6-8.noarch.rpm

$ sudo yum -y install epel-release-6-8.noarch.rpm
$ rm -f epel-release-6-8.noarch.rpm

Next let's install a collection of useful developer tools. This includes things like git, subversion, make, and the gcc complier. Most people won't use all of these tools, so you could also install tools individually if you want to be more selective. But we'll take the easy way in this tutorial.

$ sudo yum -y groupinstall 'Development Tools'

You may want to install debugging tools like gdb and valgrind as well. If you're only going to use PHP on the server side you can skip this step.

$ sudo yum -y groupinstall 'Debugging Tools'

Now let's install the Apache web server:

$ sudo yum -y install httpd mod_ssl

You'll probably want PHP, so let's install PHP along with a set of common PHP extensions:

$ sudo yum -y install php php-common

And let's install a few additional useful PHP extensions, including MySQL support, Pear, and mcrypt:

$ sudo yum -y install php-mysql php-pear php-devel php-gd php-pecl-memcache php-pspell php-snmp php-xmlrpc php-xml php-mbstring.x86_64

Finally, we'll add MySQL to complete our LAMP stack:

$ sudo yum -y install mysql mysql-server

Okay, one last thing. We'll need to manage iptables (the CentOS firewall). To make that easier let's install a GUI:

$ sudo yum -y install system-config-firewall-tui system-config-firewall

That's it for software. In the next section we'll get our web server up and running.

Next > Part 3: Starting the Web Server

 

Configure a CentOS 6.4 Web Server on Rackspace - Part 1: Securing the Server

Securing the Server

Change the Root Password

The passwd command allows you to change the root password. After entering the command you will be prompted to enter the new password two times:

# passwd

Add a New User with SUDO Privileges

The sudo command allows non-root users to temporarily take on root privileges. It's a good practice to create a new user with sudo privileges and then disable root login. So first let's create a new user. I'll use the username admin, but you can choose any username you want:

# useradd admin
# passwd admin

Now let's grant the new user sudo privileges. The following command opens the sudoers file in the vi text editor.

# visudo

Add the following line at the very bottom of the file, then save:

admin ALL=(ALL) ALL

Alternative: Add a Group With SUDO Privileges

If you plan to have several users with sudo privileges you can assign the privileges to a group and then add your users to that group. In the sudo file, replace the line we added above with this one:

%admins ALL=(ALL) ALL

This gives sudo priviliges to the group called admins. Now we need to create the admins group:

# groupadd admins

And finally, let's add our admin user to the admins group. We also have to add the user to the wheel group to allow them to use sudo:

# usermod -a -G admins,wheel admin

Grant New User SSH Access

Now that we have a user who can perform system administration tasks via sudo, let's grant him SSH access. Open the ssh config file:

# vi /etc/ssh/sshd_config

Scroll down to the section with the heading Authentication and add the following lines, then save:

# Authentication
AllowUsers admin
# or if you used the group method:
# AllowGroups admins
MaxAuthTries 6

Restart ssh:

# service sshd restart

Log In as the New User

Let's log out and log back in as our new admin user.

# exit
# this will exit the server and return you to the
# command prompt on your local computer.

# now we'll log back in as admin
$ ssh admin@12.34.56.78

If all goes well you'll be logged in as the admin user.

Disable Direct Root Login

Now that we're sure our new user can access the server, we can disable direct root login. Open the ssh config file again, but using the sudo command this time:

$ sudo vi /etc/ssh/sshd_config

Scroll down to the Authentication section and add:

# Authentication
PermitRootLogin no

Restart ssh:

$ sudo service sshd restart

Next >Part 2: Installing Packages

Configure a CentOS 6.4 Web Server on Rackspace

Updated for CentOS 6.5.

Before you can begin configuring your server, you'll first need to create a new server instance using the Rackspace cloud control panel. We're using CentOS 6.4 in this tutorial. Make note of the password — it will only be shown once! After the server is finished building, make note of the IP address as well. With the IP address and password in hand, we're ready to get started. For this example we'll assume that the IP is 12.34.56.78

Open your terminal and let's SSH to the server so we can begin:

$ ssh root@12.34.56.78

You may receive a security warning about the RSA key. If so, type yes and then hit enter. When prompted, enter your password. You should now be logged in to the server and ready to get started.

Next, let's give our server a unique name. It can be anything:

$ echo "HOSTNAME=plato" >> /etc/sysconfig/network
$ hostname "plato"

Now add a fully qualified domain name in /etc/hosts. You'll probably want to use your hostname plus your primary domain name, like so:

12.34.56.78 plato.example.com plato
# you may also wish to add your ipv6

Be sure to add an A record to your DNS that points plato.example.com to your server's IP address.

Finally set the server timezone. We'll use UTC time:

$ ln -sf /usr/share/zoneinfo/UTC /etc/localtime

Next Steps

  1. Securing the Server
  2. Installing Packages
  3. Starting the Server
  4. Apache Virtual Hosts
  5. Postfix Email Forwarding

 

Understanding logrotate on CentOS

Here is a great Slicehost article on setting up custom logrotate functions:
Part 1 | Part 2

 

Canonical Domains in Apache Conf - Add or Remove WWW

Rewrite www.example.com to example.com

<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>

Rewrite example.com to www.example.com

<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

Most RecentRSS

ArchiveRSS

March 2016 (1)
January 2016 (1)
September 2015 (1)
May 2015 (1)
April 2015 (1)
March 2015 (1)
February 2015 (2)
January 2015 (5)
September 2014 (2)
August 2014 (4)
July 2014 (1)
March 2014 (1)
November 2013 (3)
September 2013 (3)
July 2013 (6)
June 2013 (1)
May 2013 (1)
March 2013 (2)
February 2013 (3)
January 2013 (4)