Reverse proxy via nginx, using subdomain and Let's encrypt ssl certificate

What is the problem?

So, i decided to share my Octoprint instance through public interface, but got issue with actual connection via https.

Step 1. Configuring nginx.

Installed nginx and created config:

# /etc/nginx/sites-availalble/octoprint

server {
    server_name octo.hostname.com;
    location / {
        proxy_pass http://localhost:1337/;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
        proxy_http_version 1.1;

        client_max_body_size 0;
    }
}

So now it is having connection via local.ip.address:1337 and http:// octo.hostname.com. But the thing is ssl certificate warning that i decided to get rid of.

In order of that:

Step 2. Getting actual ssl certificate using certbot.

So i've installed certbot and certbot-nginx packages and performed:

# certbot --nginx 

which asked me for the server that i want get ssl certificates for. The only and actual server in the list was octoprint.
After performing that procedure, the nginx configuration file looks like that:

# /etc/nginx/sites-availalble/octoprint

server {
    listen 80;
    server_name octo.hostname.com;
    location / {
        proxy_pass http://localhost:1337/;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
        proxy_http_version 1.1;

        client_max_body_size 0;
    }

    # Added block below after reading article:
    # https://community.octoprint.org/t/reverse-proxy-configuration-examples/1107
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root html;
    } 

    listen 443 ssl; # managed by Certbot
    ssl_certificate path/to/fullchain.pem; # managed by Certbot
    ssl_certificate_key path/to/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 = octo.hostname.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name octo.hostname.com;
    return 404; # managed by Certbot
}

Looks fine to me, although i barely understand all the things "under-the-hood".

But now, when i am going to my browser and typing octo.hostname.com:

  • from the local subnet browser redirects me to my router config page, and there is actually https;
  • from the public network (using mobile LTE) page won't load.

The local.ip.address:1337 still works fine, but again it's over http and there is certificate warning.

What did you already try to solve it?

Trying to solve this issue, i've asked a GPT about octoprint configuration. The answer was to add:

ssl:
  cert: path/to/fullchain.pem
  key: path/to/privkey.pem

under "server" block of octoprint's config.yaml. No result.

Have you tried running in safe mode?

Yes.

Did running in safe mode solve the problem?

No.

Systeminfo Bundle

octoprint-systeminfo-20240215114945.zip (80.7 KB)

Additional information about your setup

Octoprint and nginx instances is running on laptop with Arch Linux os, outside of any containers. shame :dotted_line_face:
Printer model is Ender 3.
Browsers: firefox for desktop, chrome for mobile.
Router: Huawei RT-GM-2.
DNS name and subdomain is claimed properly, as conclusion of step 1 says to me. There is actual DNS name and static IP, not the DDNS or VPN.

Did you open the port on your edge system and forward these requests on port 443 and 80 to the system where you have nginx?

Do you have these ports also open on the system that nginx is running? If they are closed nginx will not be able to respond.

You are getting your routers interface from internal because your internal DNS is pointing to the outside of your network (edge). If you want the url to work internally, you will have to set up the internal DNS to point directly to your nginx system. You cannot route out and back in on the same edge device. I suggest that you get it working from the external network before trying to solve this since you don't seem to have experience with this. Focus on one side at a time. At least you have internal access with IP:Port usage for now.

1 Like

Some consumer routers support this and some don't. It's commonly called a "hairpin" and it is usually set up automatically when port forwarding is configured. Of course, if the device doesn't support hairpinning, you'd have to use split DNS or just HTTP internally, as jcassel described.

It is a bit concerning that you see the router's configuration page on the external IP address, though...

Somehow I am pretty sure they are not using a router that has hairpinning. I chose not to explain how smart I am and involve details that are likely not relevant to there issue.

Focus.

Of course not! That was such a miserable mistake, but that is the only thing i was not think about. Even after running nmap and noticing there is new service on 443 port.

So the solution is always double check port forwarding before asking the questions. Much thanks!

1 Like