How to Configure Apache Virtual Hosts on RHEL 7

Apache virtual hosts allow a single Apache HTTP Server instance to serve multiple websites on the same server, distinguishing between sites based on the incoming domain name (name-based virtual hosting) or IP address. This is the standard approach for hosting multiple websites on a shared server. On RHEL 7, Apache virtual host configurations are placed as individual .conf files in the /etc/httpd/conf.d/ directory, which Apache loads automatically. This tutorial walks through creating name-based virtual hosts, setting appropriate directory permissions, applying the correct SELinux file contexts with restorecon, and restarting Apache to serve multiple sites from a single server.

Prerequisites

  • Apache (httpd) installed and running on RHEL 7
  • Root or sudo access
  • One or more domain names, or the ability to test via curl with custom Host headers
  • Basic familiarity with Apache configuration syntax

Step 1: Understand the Apache Configuration Directory Layout

On RHEL 7, Apache’s configuration is organized as follows:

  • /etc/httpd/conf/httpd.conf — Main global configuration file. Contains the IncludeOptional conf.d/*.conf directive that loads all files in conf.d/.
  • /etc/httpd/conf.d/ — Drop-in directory for virtual host and module-specific configuration files.
  • /var/www/html/ — Default document root for the default virtual host.
  • /var/log/httpd/ — Default log directory for all virtual hosts.

Verify the include directive is present in the main config:

grep "conf.d" /etc/httpd/conf/httpd.conf

You should see:

IncludeOptional conf.d/*.conf

Step 2: Create Document Root Directories

Create a separate document root directory for each website you plan to host. Replace the example domain names with your actual domains:

sudo mkdir -p /var/www/example1.com/public_html
sudo mkdir -p /var/www/example2.com/public_html

Set ownership so Apache can read the files. Apache runs as the apache user and group on RHEL 7:

sudo chown -R apache:apache /var/www/example1.com
sudo chown -R apache:apache /var/www/example2.com

Set appropriate file permissions:

sudo chmod -R 755 /var/www/example1.com
sudo chmod -R 755 /var/www/example2.com

Create test index files for each site:

echo "<h1>Welcome to example1.com</h1>" | sudo tee /var/www/example1.com/public_html/index.html
echo "<h1>Welcome to example2.com</h1>" | sudo tee /var/www/example2.com/public_html/index.html

Step 3: Apply the Correct SELinux File Context

Because the document roots are located outside the default /var/www/html path (as subdirectories of /var/www/), you should verify and apply the correct SELinux file context. Apache requires files to have the httpd_sys_content_t type to serve them.

Check the current context:

ls -Z /var/www/example1.com/public_html/index.html

Subdirectories of /var/www/ typically inherit the correct context, but to be certain, apply it explicitly using semanage and restorecon to make the change persistent:

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example1.com(/.*)?"
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example2.com(/.*)?"
sudo restorecon -Rv /var/www/example1.com
sudo restorecon -Rv /var/www/example2.com

The restorecon command relabels the files according to the policy, and the -v flag prints each file that is relabeled. If you relocate web content in the future (for example, to /srv/www/), always run this step on the new location.

Step 4: Create the Virtual Host Configuration Files

Create a separate .conf file for each virtual host in the /etc/httpd/conf.d/ directory. Naming the files after the domain makes them easy to identify:

sudo vi /etc/httpd/conf.d/example1.com.conf

Add the following configuration:

<VirtualHost *:80>
    ServerName    example1.com
    ServerAlias   www.example1.com
    DocumentRoot  /var/www/example1.com/public_html

    <Directory /var/www/example1.com/public_html>
        Options     Indexes FollowSymLinks
        AllowOverride All
        Require     all granted
    </Directory>

    ErrorLog   /var/log/httpd/example1.com_error.log
    CustomLog  /var/log/httpd/example1.com_access.log combined
</VirtualHost>

Now create the configuration for the second site:

sudo vi /etc/httpd/conf.d/example2.com.conf
<VirtualHost *:80>
    ServerName    example2.com
    ServerAlias   www.example2.com
    DocumentRoot  /var/www/example2.com/public_html

    <Directory /var/www/example2.com/public_html>
        Options     Indexes FollowSymLinks
        AllowOverride All
        Require     all granted
    </Directory>

    ErrorLog   /var/log/httpd/example2.com_error.log
    CustomLog  /var/log/httpd/example2.com_access.log combined
</VirtualHost>

Understanding the Key Directives

  • VirtualHost *:80 — This virtual host responds to all incoming connections on port 80, regardless of the IP address. Apache uses the ServerName value to determine which virtual host to use.
  • ServerName — The primary domain name for this virtual host. Incoming requests with this value in the HTTP Host header are routed here.
  • ServerAlias — Additional domain names (such as the www. variant) that this virtual host should also respond to.
  • DocumentRoot — The filesystem path Apache uses as the root when serving files for this virtual host.
  • Directory block — Controls access and behavior for the specified directory. AllowOverride All permits .htaccess files to override configuration settings per-directory, which is required for many CMS platforms such as WordPress.
  • Options Indexes FollowSymLinks — Enables directory listing (Indexes) when no index file is found, and allows Apache to follow symbolic links. Remove Indexes in production if you do not want directory listings exposed.

Step 5: Create a Default Virtual Host

It is good practice to define a default virtual host that catches requests for any domain not explicitly configured. On RHEL 7 with Apache 2.4, you can accomplish this by creating a configuration file whose name sorts alphabetically before your site files (so it is loaded first and becomes the default):

sudo vi /etc/httpd/conf.d/000-default.conf
<VirtualHost *:80>
    ServerName   _default_
    DocumentRoot /var/www/html
    <Directory /var/www/html>
        Require all denied
    </Directory>
    CustomLog /dev/null combined
</VirtualHost>

This configuration denies access to any request that does not match a named virtual host, preventing information leakage.

Step 6: Validate the Apache Configuration

Before restarting Apache, test the configuration syntax:

sudo apachectl configtest

Or:

sudo httpd -t

A valid configuration returns:

Syntax OK

If errors are present, the output will identify the file and line number. Address all errors before restarting the service.

Step 7: Restart Apache

Restart the Apache service to apply the new virtual host configurations:

sudo systemctl restart httpd

For subsequent, smaller configuration changes (such as editing an existing virtual host), you can use a graceful reload which applies changes without dropping active connections:

sudo systemctl reload httpd

Step 8: Test the Virtual Hosts

If DNS is not yet configured, use curl with a custom Host header to test each virtual host from the server itself:

curl -H "Host: example1.com" http://localhost

Expected output:

<h1>Welcome to example1.com</h1>
curl -H "Host: example2.com" http://localhost

Expected output:

<h1>Welcome to example2.com</h1>

You can also use the -v flag to see the full HTTP request and response headers for debugging:

curl -v -H "Host: example1.com" http://localhost

List all configured virtual hosts and their associated configuration files with:

sudo httpd -t -D DUMP_VHOSTS

This output shows which file and configuration block Apache will use for each incoming domain name, which is extremely helpful for diagnosing routing issues when many virtual hosts are configured.

Conclusion

You have successfully configured name-based Apache virtual hosts on RHEL 7, enabling a single Apache instance to serve multiple independent websites. Each site has its own document root, log files, and configuration file in /etc/httpd/conf.d/. You applied SELinux contexts with restorecon to ensure Apache can read the web files, validated the configuration syntax, and tested each virtual host using curl. The AllowOverride All directive in each Directory block allows per-directory .htaccess files to control URL rewriting, caching, and access rules. The next step is typically to secure each virtual host with an SSL/TLS certificate for HTTPS connections.