Updated: 3 November 2026 · Applies to: nginx, following Mozilla's current Intermediate TLS guidance
To redirect the non-www version of a domain to www over HTTPS in nginx, you need a valid SSL certificate for both names, a server block that only redirects for the non-www host, and a separate server block that actually serves the site on www. You cannot redirect before the TLS handshake completes, so the non-www host still needs its own certificate just to accept the connection it is about to redirect.
Step 1: a redirect only block for the non-www host
Edit your site's nginx config:
vi /etc/nginx/sites-enabled/example.com.conf
Add a server block for the bare domain that does nothing but redirect:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
return 301 https://www.example.com$request_uri;
}
Step 2: the real server block for www
This is where the site actually gets served, with current TLS settings:
server {
listen 443 ssl http2;
server_name www.example.com;
access_log /var/log/nginx/www.example.com_access.log;
error_log /var/log/nginx/www.example.com_error.log;
ssl_certificate /etc/nginx/ssl/www.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/www.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
## the rest of your config: root, index, PHP-FPM and so on ##
}
The http2 flag on the listen line is the compatible syntax that works on nginx 1.24 and earlier. nginx 1.25.1 and later also accept a separate http2 on; directive instead, but the form above still works on every current version, so there is no need to change it unless you prefer the newer style.
Current nginx and OpenSSL already pick a strong, current cipher list for TLS 1.2 and 1.3 on their own, so there is no need to hand-write a long cipher string the way older guides did; TLS 1.0 and 1.1 are deprecated and should not be enabled. ssl_prefer_server_ciphers off is the current Mozilla Intermediate recommendation, since TLS 1.3 negotiates ciphers differently and current clients generally make the better choice themselves. Check Mozilla's SSL configuration generator for the exact settings matched to your installed nginx and OpenSSL versions.
Step 3: redirect plain HTTP to HTTPS too
Without this, a visitor who types the address without https:// never reaches the redirect above at all:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
Reload nginx
nginx -t
Only reload once the syntax check passes clean:
systemctl reload nginx
Test the redirect
curl -IL https://example.com/ curl -IL http://example.com/
Both should end on https://www.example.com/ with a 200 status on the final request; -L makes curl follow every redirect in the chain so you see the whole path at once.