Redirect to HTTPS and Apex Domain with Nginx location Configuration

1) The problem here is probably the Heroku load balancer. When the request of a visit comes in your app the request is HTTP again. It is just the internal routing. You can not test against $scheme. But Heroku set a $http_x_forwarded_proto header on those requests.

if ($http_x_forwarded_proto != "https") {
  return 301 https://$host$request_uri;
}

Source: https://discussion.heroku.com/t/force-ssl-and-no-www-with-nginx-configuration/856


2a) For directing to no-www you can use this:

server {
  listen <%= ENV["PORT"] %>;
  server_name "~^www\.(.*)$";
  return 301 https://$1$request_uri;
}

For testing you should use 302 instead of 301 because the browser will cache 301 redirects.

This one will redirect you to https as well. But only from the www subdomain, so you have to keep the above $http_x_forwarded_proto redirect.

2b) Another option is to use a server block with the www subdomain and redirect it to the non-www domain, like this:

server {
  listen <%= ENV["PORT"] %>;
  server_name www.example.com;

  location / {
    return 301 https://example.com$request_uri;
  }
}

server {
  listen <%= ENV["PORT"] %>;
  server_name example.com;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}

The <%= ENV["PORT"] %> code comes from a buildpack. On Heroku you can't listen to port 80.


The best way is to do a 301 redirect.

server {
    listen         80;
    return 301 https://$host$request_uri;
}