Nginx SNI Configuration: Hosting Multiple SSL Certificates
Need to host multiple domains on one server? Learn Nginx SNI configuration to manage multiple SSL certificates and streamline your SSL termination setup.
When you're scaling a side project or managing a cluster of internal services, you eventually hit the wall where one server needs to host multiple domains, each with its own SSL certificate. In the past, this meant one dedicated IP address per SSL certificate. That’s a nightmare to manage.
Today, we use Server Name Indication (SNI). It's an extension of the TLS protocol that allows the client to tell the server which hostname it's trying to reach during the initial handshake. Nginx handles this natively, making Nginx SNI configuration the standard way to host multiple sites on a single machine.
The Problem: Why SSL Termination Gets Messy
If you don't use SNI, Nginx will default to the first SSL certificate it finds in the configuration for any incoming request. If you have site-a.com and site-b.com on the same server, a visitor hitting site-b.com might see a browser warning because Nginx served the certificate for site-a.com.
I’ve spent hours debugging "Not Secure" browser warnings only to realize my Nginx server blocks were misaligned. Before you dive into the config, ensure your DNS is pointing correctly and your certificates are valid. If you are just starting out with your setup, check out my guide on Nginx SSL configuration: Automate Let's Encrypt with Certbot to get those certs generated first.
Configuring Your Server Blocks
The key to successful SSL termination is defining separate server blocks for each domain. You don't need to do anything "special" to enable SNI; Nginx detects it automatically as long as you provide the correct ssl_certificate and ssl_certificate_key paths in each block.
Here is what a standard, clean configuration looks like for two distinct domains:
NGINX# Domain A configuration server { listen 443 ssl; server_name site-a.com; ssl_certificate /etc/letsencrypt/live/site-a.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/site-a.com/privkey.pem; location / { proxy_pass http://localhost:3000; # ... standard proxy headers } } # Domain B configuration server { listen 443 ssl; server_name site-b.com; ssl_certificate /etc/letsencrypt/live/site-b.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/site-b.com/privkey.pem; location / { proxy_pass http://localhost:4000; # ... standard proxy headers } }
Essential Best Practices
When you're dealing with multiple SSL certificates Nginx needs to juggle, keep these points in mind:
- Listen on 443: Both blocks must listen on port 443 with the
ssldirective. Nginx uses theserver_nameto pick the right cert based on the SNI header. - Default Server: If you want to catch traffic that doesn't match a specific domain, define a
default_serverblock. I usually point this to a generic 404 or a landing page. - Security Headers: Don't forget to harden your connections. I always apply standard security headers to prevent common attacks, as detailed in my guide on Nginx Security Headers: A Practical Guide to Hardening Your Server.
- Test Before Reload: Always run
nginx -tbefore reloading. A syntax error in one server block will bring down the entire Nginx process, affecting all your hosted sites.
Comparison: SNI vs. Non-SNI
Most modern environments use SNI exclusively. Here is why the old way is effectively dead:
| Feature | SNI (Modern) | IP-Based (Legacy) |
|---|---|---|
| IP Requirements | Single IP | One IP per Domain |
| Setup Complexity | Low | High |
| Browser Support | All modern browsers | Limited |
| Scalability | High | Low |
Frequently Asked Questions
Does Nginx require special modules for SNI? No. SNI is built into the core Nginx binary. As long as your Nginx was compiled with OpenSSL support (which is standard on almost every distro), you're good to go.
What happens if a client doesn't support SNI? Legacy clients (like Windows XP's Internet Explorer) won't send the SNI header. Nginx will fall back to the "default" server block—usually the first one defined in your config. If that doesn't match, the connection will likely fail or show a certificate error.
Can I use a wildcard certificate instead?
Yes. If you have many subdomains (e.g., api.site.com, app.site.com), a single wildcard certificate is often easier to manage than individual certificates. You just point all your subdomains to the same ssl_certificate file.
If you're still struggling with the underlying infrastructure or need help getting your services production-ready, feel free to check out my VPS Server Setup, Deployment & Hardening service. Sometimes having a fresh set of eyes on your config files is the fastest way to fix those stubborn 502 errors or SSL handshake failures.
I’ve learned the hard way that Nginx configuration is rarely "set it and forget it." Keep your configs modular, test every change in a staging environment, and always keep an eye on your logs—they are the only source of truth when things go sideways.