+(91)70149-37521Subscribe Now

How to Configure Apache Virtual Hosts on Rocky Linux 9 and EL9

Apache virtual hosts let one Linux server deliver different websites for different domain names. The browser sends a hostname, and Apache matches it to the correct ServerName, document root, and log files. This guide shows how to configure Apache virtual hosts on Rocky Linux 9, AlmaLinux 9, RHEL 9, and CentOS Stream 9. It keeps […]

How to Configure Apache Virtual Hosts on CentOS

Apache virtual hosts let one Linux server deliver different websites for different domain names. The browser sends a hostname, and Apache matches it to the correct ServerName, document root, and log files.

This guide shows how to configure Apache virtual hosts on Rocky Linux 9, AlmaLinux 9, RHEL 9, and CentOS Stream 9. It keeps SELinux enabled, uses the standard EL9 configuration layout, tests every change, and explains how to add HTTPS afterward.

How Name-Based Virtual Hosts Work

Name-based virtual hosting lets several domains share the same IP address and ports. Each domain’s DNS points to the server. Apache first finds virtual hosts listening on the requested address and port, then compares the request hostname with ServerName and ServerAlias.

If no name matches, Apache uses the first virtual host for that address and port. For that reason, configuration order and a deliberate default site matter.

Prerequisites

  • A supported EL9 server with sudo access
  • Two domains or subdomains for testing
  • DNS A/AAAA records pointing to this server
  • Ports 80 and 443 allowed by the provider and local firewall
  • A backup of existing Apache configuration and website data

The examples use example.com and example.net. Replace them everywhere with domains you control.

Install and Start Apache on EL9

sudo dnf update -y
sudo dnf install -y httpd policycoreutils-python-utils
sudo systemctl enable --now httpd
sudo systemctl status httpd --no-pager

The Apache package and service are called httpd on EL9. You do not need EPEL just to install Apache. Check the current configuration before editing it:

sudo apachectl configtest

Open HTTP and HTTPS in firewalld

If firewalld is active, use its named web services:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

Keep SSH access allowed before changing a remote firewall. A cloud provider may also have a separate network firewall.

Create Separate Document Roots

sudo mkdir -p /var/www/example.com/public_html
sudo mkdir -p /var/www/example.net/public_html

Set ownership to the person or deployment account that maintains the files. Apache only needs read access for a static site:

sudo chown -R $USER:$USER /var/www/example.com /var/www/example.net
sudo find /var/www/example.com /var/www/example.net -type d -exec chmod 755 {} \;
sudo find /var/www/example.com /var/www/example.net -type f -exec chmod 644 {} \;

Avoid chmod -R 777. Applications that need write access should receive it only for their specific upload, cache, or data directories.

Add a Test Page for Each Domain

echo '<h1>example.com is working</h1>' | sudo tee /var/www/example.com/public_html/index.html
echo '<h1>example.net is working</h1>' | sudo tee /var/www/example.net/public_html/index.html

An index.html file is convenient for testing, but Apache can serve many file types and applications. The application and DirectoryIndex settings decide the entry file.

Keep SELinux Enabled

Do not disable SELinux to make Apache work. Content under /var/www normally receives the correct httpd_sys_content_t label, but restore and verify it after copying files:

sudo restorecon -Rv /var/www/example.com /var/www/example.net
ls -Zd /var/www/example.com/public_html /var/www/example.net/public_html

If you place website data outside /var/www, define a persistent SELinux file-context rule instead of using a temporary chcon workaround:

sudo semanage fcontext -a -t httpd_sys_content_t '/srv/example.com(/.*)?'
sudo restorecon -Rv /srv/example.com

Create Apache Virtual Host Files

On EL9, Apache automatically includes files ending in .conf from /etc/httpd/conf.d/. There is no need to copy Debian’s sites-available layout or edit the main file just to include a site.

Create the first file:

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

    <Directory "/var/www/example.com/public_html">
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

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

Create /etc/httpd/conf.d/example.net.conf with the matching domain and path:

<VirtualHost *:80>
    ServerName example.net
    ServerAlias www.example.net
    DocumentRoot "/var/www/example.net/public_html"

    <Directory "/var/www/example.net/public_html">
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    ErrorLog /var/log/httpd/example.net_error.log
    CustomLog /var/log/httpd/example.net_access.log combined
</VirtualHost>

Options -Indexes prevents a directory listing when an index file is absent. Keep AllowOverride None unless the application genuinely uses .htaccess; then allow only the features it needs.

Test Before Reloading Apache

sudo apachectl configtest
sudo apachectl -S

The test must say Syntax OK. The -S output shows which domain maps to each file and which virtual host is the default. When it is correct, reload without dropping active connections:

sudo systemctl reload httpd

Test Before DNS Is Live

You can send a temporary Host header from the server:

curl -H 'Host: example.com' http://127.0.0.1/
curl -H 'Host: example.net' http://127.0.0.1/

This confirms Apache’s matching, but it does not test public DNS or external firewalls. After DNS changes, use dig and test each public URL.

Add HTTPS to Every Virtual Host

Get a trusted certificate only after the domain resolves publicly and HTTP works. Use your organization’s approved ACME client or certificate process. Back up the Apache files, check what the client will change, and keep separate HTTPS configuration for each site.

Afterward, verify the certificate, HTTP-to-HTTPS redirect, renewal timer, and configuration:

sudo apachectl configtest
sudo systemctl reload httpd
curl -I https://example.com
curl -I https://example.net

Troubleshooting Virtual Hosts

The Wrong Website Appears

Run apachectl -S. Check DNS, ServerName, ServerAlias, configuration order, and whether the request used the expected hostname.

Apache Returns 403 Forbidden

Check directory traversal permissions, the <Directory> block, SELinux labels, and the error log. Do not disable SELinux or grant world-write permission as a shortcut.

Apache Will Not Reload

Run apachectl configtest and inspect journalctl -u httpd. Restore the backed-up configuration if needed.

PHP or an Application Needs to Write Files

Give the runtime access only to required directories and apply the correct SELinux writable-content label. Follow the application’s and Red Hat’s security documentation rather than changing the whole document root to 777.

Frequently Asked Questions

How many domains can one Apache server host?

Apache can host many name-based sites on one IP. The practical limit comes from CPU, RAM, storage, traffic, application load, administration, and security requirements.

Should SELinux be disabled for Apache?

No. Keep it enforcing and apply the proper file labels and booleans for the site’s actual needs.

Where do EL9 virtual-host files go?

A clean approach is one .conf file per site under /etc/httpd/conf.d/, which the standard configuration includes automatically.

Conclusion

You have configured two Apache name-based virtual hosts on EL9, kept SELinux protection, tested domain matching, and prepared the sites for HTTPS. Repeat the directory, configuration, validation, DNS, and certificate steps for each additional domain.

For the next security steps, see our server hardening checklist and SSH configuration guide.


Reviewed and updated: August 2026. The procedure was checked against Red Hat’s official RHEL 9 web-server guide and Apache’s official name-based virtual-host documentation.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to Our Newsletter

Get free how-to tutorials and over 700+ courses. Seo tips, create a wordpress, or learn a new skill.