0
0
Nginxdevops~5 mins

SNI for multiple SSL certificates in Nginx - Commands & Configuration

Choose your learning style9 modes available
Introduction
When you want to host multiple websites securely on the same server using HTTPS, you need a way to serve the right SSL certificate for each website. SNI (Server Name Indication) lets the server know which certificate to use based on the website name the visitor wants.
When you host two or more websites on the same server and want each to have its own HTTPS certificate.
When you want to save IP addresses by using one IP for multiple secure websites.
When you need to add a new secure website without buying a new server or IP address.
When you want visitors to see the correct security lock icon for each website.
When you want to avoid browser warnings about wrong certificates on your sites.
Config File - nginx.conf
nginx.conf
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    location / {
        root /var/www/example.com;
        index index.html;
    }
}

server {
    listen 443 ssl;
    server_name example.org;

    ssl_certificate /etc/nginx/ssl/example.org.crt;
    ssl_certificate_key /etc/nginx/ssl/example.org.key;

    location / {
        root /var/www/example.org;
        index index.html;
    }
}

server {
    listen 80;
    server_name example.com example.org;
    return 301 https://$host$request_uri;
}

This configuration defines two separate server blocks for two websites: example.com and example.org.

Each server block listens on port 443 with SSL enabled and uses its own SSL certificate and key files.

The last server block listens on port 80 (HTTP) and redirects all requests to HTTPS for both domains.

This setup uses SNI to serve the correct SSL certificate based on the requested domain name.

Commands
Check the Nginx configuration for syntax errors before applying it.
Terminal
sudo nginx -t
Expected OutputExpected
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload Nginx to apply the new configuration without stopping the server.
Terminal
sudo systemctl reload nginx
Expected OutputExpected
No output (command runs silently)
Test that example.com serves the correct SSL certificate and website content.
Terminal
curl -v https://example.com
Expected OutputExpected
* Rebuilt URL to: https://example.com/ * Trying 127.0.0.1... * Connected to example.com (127.0.0.1) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: CN=example.com * start date: Apr 1 00:00:00 2024 GMT * expire date: Apr 1 23:59:59 2025 GMT * subjectAltName: host "example.com" matched cert's "example.com" > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/7.68.0 > Accept: */* <html>...</html>
Test that example.org serves its own SSL certificate and website content correctly.
Terminal
curl -v https://example.org
Expected OutputExpected
* Rebuilt URL to: https://example.org/ * Trying 127.0.0.1... * Connected to example.org (127.0.0.1) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: CN=example.org * start date: Apr 1 00:00:00 2024 GMT * expire date: Apr 1 23:59:59 2025 GMT * subjectAltName: host "example.org" matched cert's "example.org" > GET / HTTP/1.1 > Host: example.org > User-Agent: curl/7.68.0 > Accept: */* <html>...</html>
Key Concept

If you remember nothing else from this pattern, remember: SNI lets one server use multiple SSL certificates by choosing the right one based on the website name requested.

Common Mistakes
Using the same SSL certificate for all domains without configuring separate server blocks.
Visitors to other domains will get certificate warnings because the certificate does not match the domain name.
Create separate server blocks with their own ssl_certificate and ssl_certificate_key for each domain.
Not reloading Nginx after changing the configuration.
Nginx keeps running the old configuration, so changes do not take effect.
Run 'sudo nginx -t' to check config, then 'sudo systemctl reload nginx' to apply changes.
Forgetting to redirect HTTP (port 80) traffic to HTTPS.
Users can access the site insecurely, which defeats the purpose of SSL certificates.
Add a server block listening on port 80 that redirects all requests to HTTPS.
Summary
Create separate server blocks in Nginx for each domain with its own SSL certificate.
Use 'nginx -t' to check configuration syntax before reloading Nginx.
Reload Nginx to apply changes and test each domain with curl to verify the correct certificate is served.