Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx TLS-SNI: Use hostname dependent SSL for HTTPS

Tags:

nginx

I need to use two different ssl certs with nginx pointing to the same app.

https://domain1.com points to 1.1.1.1
https://domain2.com points to 1.1.1.1 .
.
.
.
https://domainN.com points to 1.1.1.1

Tried the following:

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



server {

    listen 443 ssl;
    server_name domain1.com;
    root /app/dist;

    index index.html;

    ssl_certificate /etc/nginx/ssl/d1/certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/d1/private.key;

    location / {

        try_files $uri $uri/ /index.html;

    }

}

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



server {

    listen 443 ssl;
    server_name domain2.com;
    root /app/dist;

    index index.html;

    ssl_certificate /etc/nginx/ssl/d2/certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/d2/private.key;

    location / {

        try_files $uri $uri/ /index.html;

    }

}

This doesn't work, it just loads the first cert resulting in invalid cert when accessed using the second domain.

The domain certs can't be combined. I can't spin two different instances for nginx as the case needs to help me out with n-Domains pointing to same IP preferably using one nginx server.

Is there a way out?

like image 543
Utkarsh Narain Srivastava Avatar asked Aug 31 '25 22:08

Utkarsh Narain Srivastava


1 Answers

Thanks to Richard Smith for pointing out just the right stuff!

So, to setup nginx to use different cert-key pair for domains pointing to the same nginx we have to rely on TLS-SNI (Server Name Indication), where the domain name is sent un-encrypted text as a part of the handshake. This helps nginx to decide which cert-key pair to use for the incoming secure request.

More can be read about SNI here.

Moving on to the configuration.

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



server {

    listen 443 ssl;
    server_name domain1.com;
    root /app/dist;
    index index.html;
    ssl_certificate /etc/nginx/ssl/d1/certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/d1/private.key;

    location / {    
        try_files $uri $uri/ /index.html;
    }
}


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



server {

    listen 443 ssl;
    server_name domain2.com;
    root /app/dist;
    index index.html;
    ssl_certificate /etc/nginx/ssl/d2/certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/d2/private.key;

    location / {    
        try_files $uri $uri/ /index.html;
    }
}

The above config forwards HTTP (80) for both domain1 and domain2 to respective HTTPS (443) server blocks, where respective cert-key pairs are loaded.
The HTTPS (443) request is handled directly.
nginx decides which block to hit by picking the server name using SNI.

like image 195
Utkarsh Narain Srivastava Avatar answered Sep 04 '25 23:09

Utkarsh Narain Srivastava