When your SSL certificate is issued for mydomain.com
but not for www.mydomain.com
, browsers will show security warnings for HTTPS requests to the www version. This happens because the certificate doesn't cover the www subdomain.
Here's the proper way to handle all redirects while maintaining SSL security:
# HTTP to HTTPS redirect for both www and non-www
server {
listen 80;
server_name www.mydomain.com mydomain.com;
return 301 https://mydomain.com$request_uri;
}
# HTTPS www to non-www redirect
server {
listen 443 ssl;
server_name www.mydomain.com;
ssl_certificate /usr/local/nginx/conf/public.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
return 301 https://mydomain.com$request_uri;
}
# Main HTTPS server block
server {
listen 443 ssl;
server_name mydomain.com;
ssl_certificate /usr/local/nginx/conf/public.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
root /var/www/mysite;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
- Used
return 301
instead ofrewrite
for better performance - Properly separated the SSL configuration for www and non-www versions
- Fixed the
SCRIPT_FILENAME
parameter to use$document_root
- Added proper
try_files
directive for better URI handling
After implementing these changes, test all possible combinations:
curl -I http://www.mydomain.com
curl -I http://mydomain.com
curl -I https://www.mydomain.com
curl -I https://mydomain.com
All www requests should return 301 redirect status to the non-www HTTPS version.
When your SSL certificate only covers the base domain (mydomain.com) but not the www subdomain (www.mydomain.com), browsers will throw security warnings for HTTPS requests to the www version. This occurs because:
- The certificate doesn't validate www.mydomain.com
- Nginx is attempting to serve HTTPS content for an unvalidated domain
- The redirect happens after the SSL handshake, which is too late
Here's the proper way to configure this in Nginx:
# HTTP server block - handles both www and non-www
server {
listen 80;
server_name www.mydomain.com mydomain.com;
return 301 https://mydomain.com$request_uri;
}
# HTTPS server block for www - ONLY for redirect
server {
listen 443 ssl;
server_name www.mydomain.com;
ssl_certificate /usr/local/nginx/conf/public.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
return 301 https://mydomain.com$request_uri;
}
# Main HTTPS server block
server {
listen 443 ssl;
server_name mydomain.com;
ssl_certificate /usr/local/nginx/conf/public.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
root /var/www/mysite;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
}
}
The original configuration had several issues that we've fixed:
- Separate SSL server block specifically for www redirect
- Using
return 301
instead ofrewrite
for better performance - Proper use of
$request_uri
instead of regex capture groups - Correct fastcgi_param SCRIPT_FILENAME using $document_root
After implementing these changes, verify the redirects work correctly:
curl -I http://www.mydomain.com
curl -I http://mydomain.com
curl -I https://www.mydomain.com
curl -I https://mydomain.com
All www requests should return 301 status code pointing to the non-www HTTPS version.
For future certificates, consider:
- Getting a wildcard certificate (*.mydomain.com)
- Using Let's Encrypt with DNS-01 challenge
- Adding Subject Alternative Names (SANs) for both domains