2

I'm deploying a web on an Nginx server. Nginx is configured with both http and https versions, like this:

upstream stream {
    server unix:///home/project/project.sock;
}

server {
    listen 443;

    ssl on;
    ssl_certificate certificate.crt;
    ssl_certificate_key server.key;

    server_name server.com;
    server_name *.server.com;
    client_max_body_size 0;
    charset utf-8;

    # Main
    location / {
        uwsgi_pass stream;

        # Parametros de uWSGI
        uwsgi_param  QUERY_STRING       $query_string;
        uwsgi_param  REQUEST_METHOD     $request_method;
        uwsgi_param  CONTENT_TYPE       $content_type;
        uwsgi_param  CONTENT_LENGTH     $content_length;

        uwsgi_param  REQUEST_URI        $request_uri;
        uwsgi_param  PATH_INFO                      $document_uri;
        uwsgi_param  DOCUMENT_ROOT      $document_root;
        uwsgi_param  SERVER_PROTOCOL    $server_protocol;

        uwsgi_param  REMOTE_ADDR        $remote_addr;
        uwsgi_param  REMOTE_PORT        $remote_port;
        uwsgi_param  SERVER_ADDR        $server_addr;
        uwsgi_param  SERVER_PORT        $server_port;
        uwsgi_param  SERVER_NAME        $server_name;

        uwsgi_param UWSGI_SCHEME    https;
    }
}

server {
    listen 80;
    server_name server.com;
    server_name *.server.com;
    client_max_body_size 0;
    charset utf-8;

    # Main
    location / {
        uwsgi_pass  stream;

        # Parametros de uWSGI
        uwsgi_param  QUERY_STRING       $query_string;
        uwsgi_param  REQUEST_METHOD     $request_method;
        uwsgi_param  CONTENT_TYPE       $content_type;
        uwsgi_param  CONTENT_LENGTH     $content_length;

        uwsgi_param  REQUEST_URI        $request_uri;
        uwsgi_param  PATH_INFO                      $document_uri;
        uwsgi_param  DOCUMENT_ROOT      $document_root;
        uwsgi_param  SERVER_PROTOCOL    $server_protocol;

        uwsgi_param  REMOTE_ADDR        $remote_addr;
        uwsgi_param  REMOTE_PORT        $remote_port;
        uwsgi_param  SERVER_ADDR        $server_addr;
        uwsgi_param  SERVER_PORT        $server_port;
        uwsgi_param  SERVER_NAME        $server_name;

        uwsgi_param UWSGI_SCHEME    http;
    }
}

All works correctly, but the browser is always selecting the HTTP version when you type server.com, and I want it to select the HTTPS version by default.

How can I do it?

4 Answers 4

3

If you only want to serve over HTTPS, then you need to redirect all HTTP requests in your HTTP server block:

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

You can then remove all the other config you have in your HTTP server as it will never be used.

Sign up to request clarification or add additional context in comments.

2 Comments

I need both versions, because I don't want the API to use HTTPS.
In that case you can't prevent a browser from fetching over HTTP. You could consider keeping your API on a separate HTTP-only subdomain.
2

I have been using the following approach:

server {
    listen      80;
    server_name www.yourdomain.com *.yourdomain.com;
    rewrite     ^ https://$server_name$request_uri? permanent;
}

What is does is basically redirecting the connection to a https (secure ssl) if the connection is normal http. I hope it helps.

Comments

2

Answer found,

Turns out it is possible to have both HTTP and HTTPS servers and choose HTTPS by default. I just had to mix the two servers of the conf file in one, just like:

server {
    listen 80;
    listen 443 default_server ssl;

    ssl_certificate certificate.crt;
    ssl_certificate_key server.key;

    server_name server.com;
    server_name *.server.com;
    client_max_body_size 0;
    charset utf-8;
...
}

2 Comments

I don't see how that stops a browser from requesting a HTTP connection?
@solarissmoke I guess it's because of the "default_server" tag
1

You can't control what the browser does (unfortunately); by default if the user doesn't type the scheme (that's the technical name for the http:// part of the URL); then the browser will default to http.

If you want to serve the site only over https://, you have to redirect all requests to the https:// version.

You have to be careful here, if you implement a blind redirect as suggested by solarissmoke, any POST requests will fail and not redirect appropriately.

A more compatible approach to redirection is to check the type of request:

server {
    listen   80;
    server_name example.com;

    location / {
      if ($request_method = GET) {
        rewrite  ^ https://$host$request_uri? permanent;
      }
      return 405;
    }
}

You can then add further checks to redirect only the traffic you want to https.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.