nginx: remove www and force SSL connections

The Problem

If you’re like me and you cannot stand the age-old practice of having www in your domain names, then it’s easy to force anyone who types in www.yoursite.com to be redirected to yoursite.com while also forcing SSL connections.

Before you begin, make sure you have your SSL certificate set up and ready to go, and that you’ve already tested that it works on your nginx configuration.

You can also exclude certain pages or folders from this enforced SSL, say if you want insecure content on certain pages. You can see this in action here: https://pyronexus.com/forum/ (click “Live Streams” at the top and you’ll be forwarded to a non-https link).

The Solution

  1. Open up the configuration for your site, mine is /etc/nginx/sites-enabled/pyronexus.com.
  2. Add the following server directive, adjusting the variables as needed:

    server {
            server_name
                    www.your-site.com
            ;
    
            listen 80;
            listen 443 ssl;
    
            ssl_certificate ssl/your-certificate.crt;
            ssl_certificate_key ssl/your-certificate.key;
    
            return 301 https://your-site.com$request_uri;
    }

    This directive will force any www connections, be it through SSL or non-SSL, to non-www.

  3. Add another directive. Although in this directive you can add any exclusions of pages you don’t want to be SSL-enabled. Add them before the location ~ / {} directive (I’ve included an example in there, which excludes http://your-site.com/forum/pages.php from HTTPS connections):

    server {
            server_name
                    your-site.com
            ;
    
            listen 80 default;
    
            root /your/site/root;
    
            access_log /your/logs/location/access.log;
            error_log /your/logs/location/error.log;
    
            include global.conf;
    
            # This excludes forum/pages.php from being forced through HTTPS
            location ~ ^/forum/pages\.php$ {
                    include php.conf;
            }
    
            # This will force any http:// connections through https://
            location ~ / {
                    return 301 https://your-site.com$request_uri;
            }
    }
  4. Add a third, and final directive. This one is the directive that handles all SSL connections. You’ll need to put any exclusions you put above in here as well, and redirect people to a http connection:

    server {
            server_name
                    your-site.com
            ;
    
            listen 443 default ssl;
    
            ssl_certificate ssl/your-site.crt;
            ssl_certificate_key ssl/your-site.key;
    
            root /your/site/root;
    
            access_log /your/logs/location/access.log;
            error_log /your/logs/location/error.log;
    
            include global.conf;
    
            # This will force forum/pages.php through http://
            location ~ ^/forum/pages\.php$ {
                    return 301 http://your-site.com$request_uri;
            }
    
            include php.conf;
    }
  5. That’s it! Test your configuration out!

If you’re wondering what’s in my global.conf and php.conf, then here they are:
global.conf:

# Tries to access the file directly before handing over to index.php
location / {
        try_files $uri $uri/ /index.php?$args =404;
}

# Exclude common static file formats from logging and cache as long as possible
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|txt)$ {
        access_log off;
        log_not_found off;
        expires max;
}

# Deny access to files that start with a dot, such as .htaccess
location ~ /\. {
        deny all;
}

# Deny access to php files in folders named uploads and files (this is to prevent people uploading php files and executing them)
location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
}

php.conf:

# Pass all php files to php5-fpm
location ~ \.php$ {
        try_files $uri =404;

        include fastcgi_params;

        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
}

Leave a Comment

Skip to toolbar