May 18, 2018

Redirect HTTP to HTTPS in Nginx

^ Ad space to help offset hosting costs :D

A common task is redirecting any HTTP request to HTTPS, so our applications and sites are always using SSL certificates.

In Nginx, we generally want to avoid if statements. Similar to how we redirect between www and non-www subdomains, we'll use a server block to redirect HTTP to HTTPS requests.

Redirect All HTTP

One method I like to do is catch-all port 80 (http) requests and redirect them to port 443 (https).

This works when you know you want all configured sites to definitely only use https.

server {
    listen 80 default_server;

    server_name _;

    return 301 https://$host$request_uri;
}

This listens on port 80. It's also the port 80 default server. It's assumed that it's the only server block listening on port 80.

The server_name is _, which matches any hostname used.

Finally, we return a 301 redirect to the https version of whatever URI was requested. We know all requests reaching this server block is http, because it only listens for port 80 requests.

Redirect Specific Sites

We can redirect only specific sites also. This is better if you have multiple apps/sites and not all of them should be forced to use SSL certificates.

server {
    listen 80;

    server_name foo.com;
    return 301 https://foo.com$request_uri;
}

Here we listen on port 80 for http requests, but we don't make it the default server. Instead, it is only listening for requests made to the hostname foo.com (where the Host HTTP header is set to foo.com).

It returns a 301 redirect to the https version of the URI given, but hard-codes the hostname (foo.com).

App Configuration

Our sites/apps can then be set to listen on port 443 for SSL connections only.

server {
    listen 443 ssl default_server;
    server_name foo.com;
}

server {
    listen 443 ssl;
    server_name bar.com;
}

# and so on...

Any site can be the default_server for port 443. That's up to you to set and likely won't matter in practice.

All Topics