Enable Name-Based SSL Hosting Using SNI Without a Dedicated IP Address
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:
- A Linux server with Apache installed.
- Root or sudo access.
- Apache
mod_sslenabled. - DNS records for all domains pointing to the same server IP.
- A valid SSL certificate and private key for each domain.
- 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.
