How to Force HTTPS and Redirect www to Non-www in Nginx with Proper SSL Configuration


3 views

Modern web best practices strongly recommend using either www or non-www consistently, with HTTPS enforced. Having both versions accessible creates duplicate content issues for SEO and splits your analytics data. Here's how to properly configure this in Nginx.

For a simple HTTP to HTTPS and www to non-www redirect, add this server block to your Nginx configuration (usually in /etc/nginx/sites-available/yourdomain.conf):

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

For a production setup with SSL, you'll need two server blocks:

# Redirect all www and non-www HTTP to HTTPS non-www
server {
    listen 80;
    server_name www.example.com example.com;
    return 301 https://example.com$request_uri;
}

# Main SSL configuration for non-www
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;
    
    # Other SSL configurations...
    # Your main website configuration...
}

Some special considerations for robust implementation:

# Additional protection against direct IP access
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    return 444;
}

# Alternative if you prefer www version
server {
    listen 443 ssl;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
}

After making changes, always test your configuration:

sudo nginx -t  # Test configuration
sudo systemctl reload nginx  # Apply changes

Verify with curl or your browser that all variations redirect properly:

curl -I http://example.com
curl -I http://www.example.com
curl -I https://www.example.com

When configuring web servers, duplicate content issues arise when both www.example.com and example.com serve identical content. Search engines treat these as separate websites, potentially harming SEO rankings. A permanent 301 redirect is the standard solution.

Here's the most efficient way to implement this in Nginx:

server {
    listen 80;
    listen [::]:80;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com;
    # Your primary server configuration here
    root /var/www/example.com;
    index index.html;
    # Other directives...
}

For SSL/TLS configurations, you'll need to handle both HTTP and HTTPS redirects:

server {
    listen 80;
    listen [::]:80;
    server_name www.example.com example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.com;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    # Primary SSL configuration
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    # Your main site configuration...
}

After making changes:

sudo nginx -t
sudo systemctl reload nginx

Test using curl to verify the redirect works properly:

curl -I http://www.example.com
curl -I https://www.example.com
  • Ensure your DNS has proper A/AAAA records for both www and root domain
  • Verify SSL certificates cover both variants (or use wildcard certs)
  • Check for infinite redirect loops when combining with other rules
  • Update any hardcoded absolute URLs in your application

The redirect adds minimal overhead (typically <5ms). For optimal performance:

  • Keep redirects at the web server level rather than application level
  • Use keepalive connections to reduce TCP handshake overhead
  • Ensure proper caching headers are set for the redirect response