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
sudoaccess - One or more domain names, or the ability to test via
curlwith 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 theIncludeOptional conf.d/*.confdirective that loads all files inconf.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 theServerNamevalue to determine which virtual host to use.ServerName— The primary domain name for this virtual host. Incoming requests with this value in the HTTPHostheader are routed here.ServerAlias— Additional domain names (such as thewww.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.Directoryblock — Controls access and behavior for the specified directory.AllowOverride Allpermits.htaccessfiles 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. RemoveIndexesin 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.