RHCE – How To Set Up Apache Virtual Hosts on CentOS/RHEL 7

Virtual Hosts is one of Apache’s most powerful and commonly used feature. Virtual Hosts (aka vhosts) let’s allows you to host multiple websites on a single machine. There are 2 big advantages to this:

  • Rather than needing one ip address per website, you know just need one ip address for the machine.
  • A lot of machines capacity might not get used if it just hosts a single website. So having multiple websites on a single machine will make better use of your machine’s computing capacity

There are a few ways to setup vhosts, but we’ll walk through one of typical most common ways to create vhosts. In our example we have 2 websites that we want to host on our box, they are:

  • example.com
  • example.net

To start with we first need to create a content directory of each website, we’ll choose:

$ mkdir  /var/www/example_com
$ mkdir  /var/www/example_net
$ chown apache:apache /var/www/example_com
$ chown apache:apache /var/www/example_net
$ ll -Z /var/www/ | grep example
drwxr-xr-x. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 example_com
drwxr-xr-x. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 example_net

Now let’s create a dummy home page for each website:

$ echo 'hello example.com' > /var/www/example_com/index.html
$ chown apache:apache /var/www/example_com/index.html
$ echo 'hello example.net' > /var/www/example_net/index.html
$ chown apache:apache /var/www/example_net/index.html
$ ls -lZ /var/www/example_com/index.html
-rw-r--r--. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/example_com/index.html
$ ls -lZ /var/www/example_net/index.html
-rw-r--r--. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/example_net/index.html

Now we create the vhost config files, they are:

$ ll /etc/httpd/conf.d | grep example
-rw-r--r--. 1 apache apache  243 Mar  5 19:11 example_com.conf
-rw-r--r--. 1 apache apache  242 Mar  5 19:10 example_net.conf
$ ll -Z /etc/httpd/conf.d | grep example
-rw-r--r--. apache apache unconfined_u:object_r:httpd_config_t:s0 example_com.conf
-rw-r--r--. apache apache unconfined_u:object_r:httpd_config_t:s0 example_net.conf
$ cat /etc/httpd/conf.d/example_com.conf
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com
    DocumentRoot /var/www/example_com
    ErrorLog /var/log/httpd/example_com_error.log
    CustomLog /var/log/httpd/example_com_access.log combined
$ cat /etc/httpd/conf.d/example_net.conf
<VirtualHost *:80>
    ServerName www.example.net
    ServerAlias example.net
    DocumentRoot /var/www/example_net
    ErrorLog /var/log/httpd/example_net_error.log
    CustomLog /var/log/httpd/example_net_access.log combined

We can test the syntax of these new config files using apachectl like this:

$ apachectl configtest
Syntax OK

We can also check whether httpd is aware of our new vhosts like this:

$ httpd -D DUMP_VHOSTS
VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server www.example.com (/etc/httpd/conf.d/example_com.conf:1)
         port 80 namevhost www.example.com (/etc/httpd/conf.d/example_com.conf:1)
                 alias example.com
         port 80 namevhost www.example.net (/etc/httpd/conf.d/example_net.conf:1)
                 alias example.net
*:443                  webserver.local (/etc/httpd/conf.d/ssl.conf:56)

Since these are dummy websites for testing purposes, we don’t have public dns entries for example.com and example.net. So we need to do the dns resolution locally using /etc/hosts file. In our example, our box’s IP address is ‘’, so we add in the following lines:

$ cat /etc/hosts	webserver.local	webserver   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
<strong>   example.com</strong>
<strong>   example.net</strong>

Now we reload the configurations:

$ systemctl restart httpd

Finally we can test to see if this has worked:

[root@webserver conf.d]# curl http://example.com
hello example.com
[root@webserver conf.d]# curl http://example.net
hello example.net


In case you want to use a non-standard port to listen on. Then you need to tell SELinux about this. First you need to check what ports SELinux allows web traffic on:

$ semanage port -l | grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

Now if we want to use a non-stanard port, e.g. 3030, then first check it’s not being used elsewhere according to selinux:

$ semanage port -l | grep 3030
$ ss -atn | grep 3030

Now add this port to our SELinux rules, like this:

$ semanage port -at http_port_t -p tcp 3030

Take the RHCSA Quiz

This article is part of our RHCSA Study guide (click on the yellow tab on the far left). By the end of this article you should be able to answer the following questions:

this is now a question. Instead it's a challenge

Create a website called cb.com with the following settings:
– documentroot: /var/vhosts/cb
– listens of port 5900
– index.html contains ‘hello’
– not encrypted.
– ensure both selinux and firewalld is running

What is the command to check what ports SELinux allows web traffic through?

$ semanage port -l | grep http

What is the command to update SELinux to allow web traffic through port 3030?

$ semanage port -at http_port_t -p tcp 3030