Introduction

Server Name Indication, commonly known as SNI, is a TLS extension that allows multiple SSL-enabled websites to run on the same IP address and port. Without SNI, each HTTPS website normally required a dedicated IP address because the web server had to select the SSL certificate before knowing which domain the visitor requested.

With SNI, the client sends the requested hostname during the TLS handshake. Apache can then select the correct SSL certificate for that domain. This makes it possible to host multiple secure websites on a shared hosting server without assigning a dedicated IP address to every domain.

Older guides used mod_gnutls for SNI support. In modern Apache installations, this is no longer required. Apache with mod_ssl supports SNI, so the recommended method is to configure name-based SSL virtual hosts using mod_ssl.

Prerequisites

Before starting, make sure you have:

  1. A Linux server with Apache installed.
  2. Root or sudo access.
  3. Apache mod_ssl enabled.
  4. DNS records for all domains pointing to the same server IP.
  5. A valid SSL certificate and private key for each domain.
  6. Port 443 opened in the firewall.

Example domains used in this guide:

v1.example.org
v2.example.org

Both domains will use the same server IP address.

Step 1: Install Apache SSL Module

RHEL / CentOS / AlmaLinux / Rocky Linux

sudo dnf install httpd mod_ssl -y
sudo systemctl enable --now httpd

For older systems:

sudo yum install httpd mod_ssl -y
sudo systemctl enable --now httpd

Ubuntu / Debian

sudo apt update
sudo apt install apache2 openssl -y
sudo a2enmod ssl
sudo systemctl restart apache2

Step 2: Create Document Root Directories

Create separate document roots for each domain.

sudo mkdir -p /var/www/v1/public_html
sudo mkdir -p /var/www/v2/public_html

Create test index files.

echo "Welcome to v1.example.org" | sudo tee /var/www/v1/public_html/index.html
echo "Welcome to v2.example.org" | sudo tee /var/www/v2/public_html/index.html

Set proper ownership.

RHEL-based systems

sudo chown -R apache:apache /var/www/v1 /var/www/v2

Ubuntu / Debian

sudo chown -R www-data:www-data /var/www/v1 /var/www/v2

Step 3: Place SSL Certificates

Each domain must have its own SSL certificate and private key.

Example certificate paths:

/etc/ssl/certs/v1.example.org.crt
/etc/ssl/private/v1.example.org.key

/etc/ssl/certs/v2.example.org.crt
/etc/ssl/private/v2.example.org.key

The certificate Common Name or Subject Alternative Name should match the domain name.

For production, use a trusted SSL certificate from a Certificate Authority or Let’s Encrypt.

Step 4: Configure Apache SSL Virtual Hosts

Create a virtual host configuration file.

RHEL / CentOS

sudo vi /etc/httpd/conf.d/ssl-vhosts.conf

Ubuntu / Debian

sudo vi /etc/apache2/sites-available/ssl-vhosts.conf

Add the following configuration:

<VirtualHost *:443>
    ServerName v1.example.org
    DocumentRoot /var/www/v1/public_html

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/v1.example.org.crt
    SSLCertificateKeyFile /etc/ssl/private/v1.example.org.key

    ErrorLog /var/log/httpd/v1_ssl_error.log
    CustomLog /var/log/httpd/v1_ssl_access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName v2.example.org
    DocumentRoot /var/www/v2/public_html

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/v2.example.org.crt
    SSLCertificateKeyFile /etc/ssl/private/v2.example.org.key

    ErrorLog /var/log/httpd/v2_ssl_error.log
    CustomLog /var/log/httpd/v2_ssl_access.log combined
</VirtualHost>

For Ubuntu / Debian, log paths can be changed like this:

ErrorLog ${APACHE_LOG_DIR}/v1_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/v1_ssl_access.log combined

Step 5: Enable the Site on Ubuntu / Debian

For Ubuntu / Debian systems, enable the new SSL virtual host file:

sudo a2ensite ssl-vhosts.conf
sudo systemctl reload apache2

For RHEL-based systems, files inside /etc/httpd/conf.d/ are loaded automatically.

Step 6: Test Apache Configuration

Before restarting Apache, check the configuration syntax.

RHEL / CentOS

sudo apachectl configtest
sudo systemctl restart httpd

Ubuntu / Debian

sudo apache2ctl configtest
sudo systemctl restart apache2

Expected output:

Syntax OK

Step 7: Test SNI

Open the domains in a browser:

https://v1.example.org
https://v2.example.org

Each domain should load its own website and show its own SSL certificate.

You can also test using OpenSSL:

openssl s_client -connect SERVER_IP:443 -servername v1.example.org
openssl s_client -connect SERVER_IP:443 -servername v2.example.org

Check the certificate details in the output. The certificate shown should match the domain passed in the -servername option.

Important Notes

The first SSL virtual host acts as the default virtual host. If an old browser or client does not support SNI, Apache may return the certificate from the first virtual host.

For modern browsers and operating systems, SNI is supported by default.

Do not use the old NameVirtualHost directive on Apache 2.4. It is no longer required. Apache automatically handles name-based virtual hosts when multiple virtual hosts are configured on the same IP and port.

Do not compile mod_gnutls unless you are working on a very old legacy server. For modern servers, mod_ssl is the recommended module.

Conclusion

SNI allows multiple HTTPS websites to share the same IP address without requiring a dedicated IP for every SSL certificate. This is especially useful for shared hosting environments, where many domains are hosted on one server.

In modern Apache installations, SNI can be configured easily using mod_ssl and separate SSL virtual host blocks. Each domain can have its own certificate, private key, document root, logs, and configuration while still using the same server IP address.

This reduces IP usage, lowers hosting cost, and makes SSL hosting easier to manage.

Leave a Reply