Nginx won’t redirect from HTTP to HTTPS

nginxproxypassssl

My architecture setup is SSO service running on CentOS on NodeJS, ports 10102 and 10142, I need all requests to port 80 to be redirected to 443 externally and internally I upstream everything to the above ports of NodeJS, here's my config:

upstream sso1 {
    server localhost:10102;
    server localhost:10142;
}

server {
    listen [::]:80;
    listen 443 ssl;

    server_name www.site.business site.business;

    ssl_certificate /etc/nginx/cert.crt;
    ssl_certificate_key /etc/nginx/cert.key;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    if ($scheme = http) {
            return 301 https://$server_name$request_uri;
    }

    location / {
            proxy_pass http://sso1;
            proxy_read_timeout 90;
            proxy_redirect     http://sso1 https://www.site.business;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
    }
}

But no matter what I do, the site is still available via HTTP and HTTPS both.

Any ideas why Nginx ignores me? I've actually tried different configurations, one of them was catch all port 80 requests and 301 redirect them:

upstream sso1 {
    server localhost:10102;
    server localhost:10142;
}

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

server {
    listen 443;

    server_name www.site.business site.business;

    ssl_certificate /etc/nginx/cert.crt;
    ssl_certificate_key /etc/nginx/cert.key;
    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

location / {
    proxy_pass http://sso1;
    proxy_read_timeout 90;
    proxy_redirect     http://sso1 https://www.site.business;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}
}

Best Answer

In your top configuration you've told it to listen on 80 and 443. Here's the important parts of a config for your situation, assuming you want the site to reply on only https on the www subdomain.

The other key is you may have to set up a listener for the default domain, which services any request that hits the server.

// Listen for requests for the main website
server {
  server_name www.example.com;
  listen 443 ssl http2; // https optional, need to build Nginx with correct module

  ssl_certificatefullchain;
  ssl_certificate_key privkey;

  // locations etc
}

// Forward http requests for domain and www subdomain to main
server {
  listen 80;
  server_name example.com www.example.com;
  return 301 https://www.example.com$request_uri;
}

// Forward https requests for root domain to main
server {
  listen 443 ssl;
  server_name example.com;
  ssl_certificatefullchain;
  ssl_certificate_key privkey;
  return 301 https://www.example.com$request_uri;
}

I have this config to deal with the default

# This just prevents Nginx picking a random default server if it doesn't know which server block to send a request to
server {
  listen      80 default_server;
  server_name _;
  return      444; # This means "go away", effectively    
}

I have a big tutorial and sample config files available here.