How To Configure an Apache Virtual Host

In Apache (httpd) virtual hosts are used to host web content for multiple domains off of the same server depending on the IP address or domain name that is being used. Depending on the request received different virtual host configuration can apply, resulting in different settings and web content being served from a single web server. For example a web server with one IP address can host multiple domain names such as example.com and example.org and many more.

Here we are going to cover how to configure virtual hosts for Apache 2.4 so that we can have multiple domains serving different websites based on what is requested.


Red Hat Certified Engineer RHCE Video Course
Studying for your RHCE certification? Checkout our RHCE video course over at Udemy which is 20% off when you use the code ROOTUSER.


Example Apache Virtual Host Configuration

Virtual host configuration is typically placed within the /etc/httpd/conf/httpd.conf file, and also in unique .conf files within the /etc/httpd/conf.d directory. It is good practice to create a new .conf file within /etc/httpd/conf.d if you are adding multiple websites to be hosted from the same web server, as this keeps the configuration clean and is easier to manage. In our example we will be working with /etc/httpd/conf.d/example1.conf which will be for the website www.example.com and /etc/httpd/conf.d/example2.conf which will be for the website www.example.org.

First we’ll start with some example virtual host configuration and then discuss what each line is actually doing. For additional examples, see the Apache documentation.

The below example virtual host configuration has been saved within the /etc/httpd/conf.d/example1.conf file.

<Directory /var/www/html/example1>
    Require all granted
</Directory>

<VirtualHost *:80>
    DocumentRoot "/var/www/html/example1"
    ServerName www.example.com
    ServerAlias example.com
    ServerAdmin [email protected]
    ErrorLog "/var/log/httpd/error_log_example1"
    CustomLog "/var/log/httpd/access_log_example1" combined
</VirtualHost>

The below example virtual host configuration has been saved within the /etc/httpd/conf.d/example2.conf file.

<Directory /var/www/html/example2>
    Require all granted
</Directory>

<VirtualHost *:80>
    DocumentRoot "/var/www/html/example2"
    ServerName www.example.org
    ServerAlias example.org
    ServerAdmin [email protected]
    ErrorLog "/var/log/httpd/error_log_example2"
    CustomLog "/var/log/httpd/access_log_example2" combined
</VirtualHost>

In the above examples we have two virtual host configuration blocks. The first is for www.example.com while the second is for www.example.org. Below we will explain each line for the example1/example.com virtual host as the configuration is mostly the same between the two.

  • <Directory /var/www/html/example1> – This opens the directory tag and is used to enclose a group of directives that apply to the directory specified.
  • Require all granted – This is required to grant access, without it the Apache logs will show “authz_core:error” as the default configuration within the /etc/http/conf/httpd.conf file defines the directory of “/” with “Require all denied”.
  • </Directory> – This closes the directory tag.
  • <VirtualHost *:80> – This virtual host tag indicates that the configuration after it will apply to any IP address as per “*” on port 80, “*” can instead be modified to a particular IP address that is available on the server. The port can also be changed if the Listen directive for that port is defined within the main httpd.conf file.
  • DocumentRoot “/var/www/example1” – The document root is the directory where the content exists that Apache should serve when we visit the domain name, in this case going to www.example.com will direct us to files within the /var/www/example1 directory on the web server. The directory specified should exist and ideally contain content.
  • ServerName www.example.com – This is the unique name that the virtual host is for, in this case the virtual host configuration block is for the www.example.com website.
  • ServerAlias example.com – Alternate names can be used when matching a request and are specified with ServerAlias, these allow us to provide other name based aliases as only one ServerName is allowed per virtual host.
  • ServerAdmin [email protected] – This is an email address that is provided in error messages, allowing users to contact the web master of the web server.
  • ErrorLog “/var/log/httpd/error_log_example1” – This is the file where error logs are stored that are related to this virtualhost, which are useful when troubleshooting problems.
  • CustomLog “/var/log/httpd/access_log_example1” combined – This is where access logs are stored, for instance when a client views a web page the access requests will be logged here.
  • </VirtualHost> – This is the closing tag for the virtual host block, indicating the end of the configuration for the particular virtual host.

If any configuration within a virtual host is missing, the defaults specified in the main /etc/httpd/conf/httpd.conf file will be used instead.

The second virtual host block in the example2.conf file is mostly the same, except that it takes care of requests for www.example.org and example.org serving the content within /var/www/html/example2. Errors are logged to /var/log/httpd/error_log_example2 and access requests are logged to /var/log/httpd/access_log_example2.

The syntax of our two .conf files can be tested with the ‘apachectl configtest’ command as shown below. In this case the document root directories have not yet been created so we are given a warning and should create these.

[root@centos ~]# apachectl configtest
AH00112: Warning: DocumentRoot [/var/www/html/example1] does not exist
AH00112: Warning: DocumentRoot [/var/www/html/example2] does not exist
Syntax OK

The directories can be created with mkdir as shown below.

mkdir /var/www/html/example1
mkdir /var/www/html/example2

Now that our directories exist the warning should no longer come up. In this example I have created two index.html files with a text editor in both directories, the contents are shown below.

[root@testing ~]# cat /var/www/html/example1/index.html
example.com website
[root@testing ~]# cat /var/www/html/example2/index.html
example.org website

Before testing our virtual host configuration, any changes to Apache configuration files such as modification to virtual hosts will require the httpd service to either be restarted or reloaded to pick up the configuration changes. Apache can be reloaded to make use of configuration changes with ‘systemctl reload httpd’, for further information see our service management guide.

Testing the Virtual Hosts

Once virtual host configuration has been put in place and Apache reloaded, the relevant DNS records will need to be created so that the domains will resolve to the web server. Alternatively you can test by modifying your hosts file. In this example we can modify the /etc/hosts file and add the following entry.

127.0.0.1 example.com www.example.com example.org www.example.org

This will make these domains resolve to localhost, now we can browse the content and confirm our virtual hosts are working correctly. In this instance we are going to use the curl command to view the contents of each website.

[root@centos ~]# curl example.com
example.com website
[root@centos ~]# curl example.org
example.org website

This confirms that the correct index.html pages within /var/www/html/example1 and /var/www/html/example2 are being retrieved successfully for each domain, as defined within the virtual host configuration.

Further Information

If you get stuck or have trouble remembering any of this, remember the httpd-manual package which can be installed and viewed at http://localhost/manual.

From the main page, simply select Virtual Hosts for help on this topic.

Summary

With a few lines of virtual host configuration we can enable Apache to serve multiple websites from the same web server, allowing us to host multiple websites within the same shared hosting environment.


This post is part of our Red Hat Certified Engineer (RHCE) exam study guide series. For more RHCE related posts and information check out our full RHCE study guide.

Leave a comment ?

10 Comments.

  1. Hi, everything working fine, but i’m trying to list the files in the directory but without any luck, instead it show me the default index of Apache 123..,
    This is my configuration, can someone point me what i’m missing

    servername practice.fr
    documentroot /var/w/practice

    options indexes
    AllowOverride None
    Require all granted

    • If you’re getting the Apache testing page, try removing the configuration file found here: /etc/httpd/conf.d/welcome.conf

      If you have no index file within the directory, by default Apache will serve out this test page. If you remove that and restart Apache, you should be able to list directory contents by specifying “Options Indexes” as you have in your example.

  2. Hi Guys,

    I neeed your help with the below request.

    Please configure httpd on drdsv01zatcrh with the following security setup:

    1. Access to a virtual directory secured with https, redirected to a local URL (e.g. http://localhost:4579).
    2. Only users belonging to LDAP group “Data Integration Dashboard Users” (already created) should be allowed access to the virtual directory.

    • In this instance is there some other local service running on the same server as Apache on port 4579? So for example if you go to example.com it needs to proxy through to localhost:4579? Is that correct? Assuming this is the case, something similar to the below should get you started. I’m not completely sure about the LDAP configuration you’ll need to test that. You need to change the full distinguished name to match your environment, these are just examples. You’ll also need to provide an LDAP account and password to connect to LDAP with.

      <Directory /var/www/html/example>
          Require all granted
      </Directory>
      
      <VirtualHost *:80>
          DocumentRoot "/var/www/html/example"
          ServerName www.example.com
          ServerAlias example.com
          ServerAdmin [email protected]
          ErrorLog "/var/log/httpd/error_log_example"
          CustomLog "/var/log/httpd/access_log_example" combined
      
          ProxyRequests Off
          ProxyPass / http://127.0.0.1:4579/
          <Location />
              ProxyPassReverse http://127.0.0.1:4579/
          </Location>
      
          SSLEngine On
          SSLCertificateFile /root/www.exmaple.com.crt
          SSLCertificateKeyFile /root/www.exmaple.com.key
      
          <Location />
              Order allow,deny
              Allow from all
              AuthType Basic
              AuthName 'LDAP Login'
              AuthBasicProvider ldap
              AuthLDAPURL 'ldaps://ldap.com:636/cn=users,cn=accounts,dc=ldap,dc=com'
              AuthLDAPBindDN 'uid=user,cn=users,cn=accounts,dc=ldap,dc=com'
              AuthLDAPBindPassword 'password'
      
              Require group "Data Integration Dashboard Users"
          </Location>
      
      </VirtualHost>
      

      Please note this has not been tested and is to serve as an example to get you going.

  3. Hi Jarrod,

    Have a quick question. By adding virtual host tags, can I also configure a virtualhost on server1 but have it called by another server2 also running apache? If so what should be the virtualHost syntax? Main website is running on server2 and it has a link that will point the the virtualhost running on serverA, is it possible?

  4. In order to make it work, you need to grant permission to /var/www/html directory.
    For eg: chmod 755 /var/www/html

  5. Hi.
    I configured 2 virtual hosts.
    curl site1 and curl site2 show content of site1 and site2. But in a browser I see site1 content by url http://www.site1.my or http://www.site2.my

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>