Unable to Access HTTPS Endpoints on Different Ports with Nginx Reverse Proxy and Let's Encrypt

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. crt.sh | example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is: dashboard.bjahe.com

I ran this command: NA

It produced this output: NA

My web server is (include version): Nginx

The operating system my web server runs on is (include version): Ubuntu 22.04.2

My hosting provider, if applicable, is: digital ocean

I can login to a root shell on my machine (yes or no, or I don't know): yes

I'm using a control panel to manage my site (no, or provide the name and version of the control panel): no

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot): certbot 2.10.0

Topic Details:

I am using Godaddy as my domain registrar and have created a subdomain linked to my server's IP address on Digital Ocean. I am also using Let's Encrypt to get SSL certificates and nginx as a reverse proxy. Below is my nginx configuration file:

server {
        listen 443 http2 ssl;
        server_name <subdomain_name>;

        #Logging
        access_log /var/log/nginx/<subdomain_name>.access.log;
        error_log /var/log/nginx/<subdomain_name>.error.log;


        location /.well-known/acme-challenge/ {
                root /var/www/html/test; # Temp for generating letsencrypt
                default_type text/plain;
        }

        location / {
                proxy_set_header Host $host:$server_port;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;

                #Fix the “It appears that your reverse proxy set up is broken” error.

                proxy_pass http://127.0.0.1:3001;
                proxy_read_timeout 90;
                proxy_redirect http://127.0.0.1:3001 http://<subdomain_name>/;

                #Required for new HTTP-based CLI

                proxy_http_version 1.1;
                proxy_request_buffering off;
        }

        # SSL configuration
        ssl_certificate /etc/letsencrypt/live/<subdomain_name>/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/<subdomain_name>/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
        if ($host = <subdomain_name>) {
                return 301 https://$host$request_uri;
        } # managed by Certbot

        listen 80;
        server_name <subdomain_name>;
        return 404; # managed by Certbot
}

Setup:

I am running multiple applications that are listening on different ports with some applications being dependent on each other.

Example:

http://<subdomain_name>:3001 -> being a nginx application angular frontend application
http://<subdomain_name>:3002 -> an API that provides http://<subdomain_name>:3001 with the necessary data
http://<subdomain_name>:3003 -> another service

Problem:

When I run the domains without SSL using plain HTTP, they work fine. However, when I try to access them using HTTPS, only https://<subdomain_name>:3001 works. Endpoints like https://<subdomain_name>:3002 and https://<subdomain_name>:3003 throw an error: "This website cannot provide a secure connection <subdomain_name> has sent an invalid response. ERR_SSL_PROTOCOL_ERROR".

Expected outcome:

I want all endpoints (http and https) to work properly, and https://<subdomain_name>:3002 should be able to provide data to https://<subdomain_name>:3001 without errors.

I've tried adjusting the nginx configuration by adding different server blocks for each service, but I can't get it to work as expected. Any guidance on how to resolve this issue would be greatly appreciated.

Welcome @roger1891

You didn't show any example of using port 3002 so I can't comment on that.

But, why do you need HTTPS to work for a proxy to your own localhost? Normally you wouldn't do that. Comms are often already secure between services on the same host.

And, normally a port supports just HTTP or just HTTPS not both at the same time. Although, some services do allow that.

With that said, to do as you asked you need to configure your port 3001 service to support HTTPS and then make sure you pass the needed parameters in your proxy statements to connect properly. That is, use a URL for a hostname that appears in the cert used by your port 3001 service. Or, use settings in nginx for proxy like proxy_ssl_name and similar. See the nginx docs about those options here
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

If you want to show what you actually tried maybe someone will comment. There are numerous ways to setup such services depending on that they are. Providing a blanket answer to such a question isn't practical.

3 Likes

This sounds close to impossible.
You stated clearly that those two ports (3001 and 3002) are using HTTP:

You just can't [easily] serve HTTP and HTTPS on the same port.

If you need to do both [HTTP and HTTPS], then each such server/service will need one extra port for HTTPS.
Like...

service #1:
http://<subdomain_name>:3001
https://<subdomain_name>:4001

service #2:
http://<subdomain_name>:3002
https://<subdomain_name>:4002

service #3:
http://<subdomain_name>:3003
https://<subdomain_name>:4003

3 Likes

Hi @rg305 ,

Thanks for getting back to me. I totally understand that I cant have the same ports for HTTP and HTTPS. The main problem is that I have created a subdomain which has a letsencrypt certificate, linked to my <ip_address> and I used reverse proxy to http://subdomain:3001. Ultimately, this throws an error because now other API which now tries to use https://subdomain:3002 cant have access to subdomain and throws me this error "This website cannot provide a secure connection <subdomain_name> has sent an invalid response. ERR_SSL_PROTOCOL_ERROR" .

Here the image of the error:

1 Like

Thank you for pushing me into the right direction @MikeMcQ. This seems to be doing the trick.

2 Likes

Also wanted to thank everybody for being so open, patient and helpful. Good community.

2 Likes