nginxdigital-oceannginx-reverse-proxycertbot

Nginx, Https, reverse proxy, handshake error. Need review of 'nginx/sites-enabled/default' file.


I am hoping for a review of some code below -- it is the 'nginx/sites-enabled/default' file. I believe it may have some obvious gotchas which are preventing my site from redirecting under https. I have spent a few days reviewing the Nginx documentation but have not been able to get a handle on my problem. Thanks for your help!

Context: I am trying to set up a reverse proxy that points my domain url to localhost:3000 on my Digital Ocean server. Everything seems to be working well except for the fact my https is not resolving. I have generally followed these two tutorials: https://code.lengstorf.com/deploy-nodejs-ssl-digitalocean/ and https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04 .

When I go to my url I get: "ERR_CONNECTION_RESET". When I run curl on my server for http://localhost:3000, my html is returned as expected. When I run curl on my server for https://mysite.io I receive the error: "curl (35) gnutls_handshake() failed: Error in the pull function". All my http curl requests are redirecting properly to https, dig +short mysite.io is pointing to my server, nginx -t is coming back with no errors.

My hunch is the problem is with my 'nginx/sites-enabled/default' file, more specifically the server blocks that are handling https. The first two server blocks are from the first tutorial, the second two were automatically generated by Certbot in the second tutorial mentioned above. Thanks again for your help!

# HTTP — redirect all traffic to HTTPS
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}

# HTTPS — proxy all requests to the Node app
server {
    # Enable HTTP/2
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name mysite.io;

    # Use the Let’s Encrypt certificates
    ssl_certificate /etc/letsencrypt/live/mysite.io/fullchain.pem; # managed $
    ssl_certificate_key /etc/letsencrypt/live/mysite.io/privkey.pem; # manage$

    # Include the SSL configuration from cipherli.st
    include snippets/ssl-params.conf;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3000/;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }


}

server {
    return 301 https://$host$request_uri;

    server_name www.mysite.io; # managed by Certbot

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mysite.io/fullchain.pem; # managed $
    ssl_certificate_key /etc/letsencrypt/live/mysite.io/privkey.pem; # manage$
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = www.mysite.io) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    listen [::]:80  ;
    server_name www.mysite.io;
    return 404; # managed by Certbot

}

Solution

  • The first two blocks are unnecessary and can be removed. Then, we can take the location block from the second server block and add it to the third server block. And then, finally we can remove the 301 from the third block, ending up with this:

    server {
        server_name www.mysite.io; # managed by Certbot
    
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;
            proxy_pass http://localhost:3000/;
            proxy_ssl_session_reuse off;
            proxy_set_header Host $http_host;
            proxy_cache_bypass $http_upgrade;
            proxy_redirect off;
        }
    
        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        # change the above line to "listen 443 ssl http2" if you want http2
        ssl_certificate /etc/letsencrypt/live/mysite.io/fullchain.pem; # managed $
        ssl_certificate_key /etc/letsencrypt/live/mysite.io/privkey.pem; # manage$
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    
    }
    
    server {
        if ($host = www.mysite.io) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
    
        listen 80;
        listen [::]:80  ;
        server_name www.mysite.io;
        return 404; # managed by Certbot
    
    }