Reverse proxy configuration examples


#1

If you want to run OctoPrint behind a reverse proxy such as Nginx, HAProxy or Apache's mod_proxy you can find some configuration examples here.

Nginx

For Nginx the basic forwarding configuration is something like this:

    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include            mime.types;
        default_type       application/octet-stream;
        sendfile           on;
        keepalive_timeout  65;

        map $http_upgrade $connection_upgrade {
            default upgrade;
            '' close;
        }
  
        upstream "octoprint" {
            server 127.0.0.1:5000;
        }
    
        upstream "mjpg-streamer" {
            server 127.0.0.1:8080;
        }
    
        server {
            listen       80;
            server_name  localhost;
            
            location / {
                proxy_pass http://octoprint/;
                proxy_set_header Host $http_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-Scheme $scheme;
                proxy_http_version 1.1;

                client_max_body_size 0;    
            }

            location /webcam/ {
                proxy_pass http://mjpg-streamer/;
            }

            # redirect server error pages to the static page /50x.html
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }

:warning: Warning

Be extra sure to include proxy_http_version 1.1 or the web socket connection will fail.

If you want to serve OctoPrint on a different base URL than / (e.g. /octoprint/), you'll need to adjust its location definition slightly by changing the location path itself, the proxy_pass target and adding the X-Script-Name header:

    location /octoprint/ {
        proxy_pass http://octoprint/; # make sure to add trailing slash here!
        proxy_set_header Host $http_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-Scheme $scheme;
        proxy_set_header X-Script-Name /octoprint;
        proxy_http_version 1.1;

        client_max_body_size 0;    
    }

HAProxy

If you just want to run OctoPrint on the server root of the reverse proxy with mjpg-streamer running under /webcam, the following configuration is sufficient:

global
        maxconn 4096
        user haproxy
        group haproxy
        daemon
        log 127.0.0.1 local0 debug

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        retries 3
        option redispatch
        option http-server-close
        option forwardfor
        maxconn 2000
        timeout connect 5s
        timeout client  15min
        timeout server  15min

frontend public
        bind *:80
        use_backend webcam if { path_beg /webcam/ }
        default_backend octoprint

backend octoprint
        option forwardfor
        server octoprint1 127.0.0.1:5000

backend webcam
        reqrep ^([^\ :]*)\ /webcam/(.*)     \1\ /\2
        server webcam1  127.0.0.1:8080

If you want to make it run on a different base URL, you'll need to instruct HAProxy to send a X-Script-Name header with each forwarded request to make OctoPrint generate correct URLs on its pages:

backend octoprint
  reqrep ^([^\ :]*)\ /octoprint/(.*)  \1\ /\2
  reqadd X-Script-Name:\ /octoprint
  option forwardfor
  server octoprint1 127.0.0.1:5000

If you also want to run it SSL encrypted with HAProxy being the SSL terminator, you should also send a header of X-Scheme with each forwarded request to indicate https requests. You can configure this in the backend section like this:

backend octoprint
  ...
  reqadd X-Scheme:\ https if { ssl_fc }
  ...

Apache

:warning: Not recommended

Apache is somewhat heavy weighted compared to other options, and the configuration is also a bit messy. If possible it's highly recommended to rather use Nginx or haproxy.

For Apache (with mod_proxy, mod_proxy_http, mod_proxy_wstunnel and mod_headers enabled) the basic configuration is something among these lines:

<Location />
  ProxyPass http://<myOctoPrintHost>:5000/
  ProxyPassReverse http://<myOctoPrintHost>:5000/

  RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} =websocket [NC]
  RewriteRule .* ws://<myOctoPrintHost>%{REQUEST_URI} [P,L]
</Location>

or with https:

<Location />
  RequestHeader set X-SCHEME https
  ProxyPass http://<myOctoPrintHost>:5000/
  ProxyPassReverse http://<myOctoPrintHost>:5000/

  RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} =websocket [NC]
  RewriteRule .* ws://<myOctoPrintHost>%{REQUEST_URI} [P,L]
</Location>

If you want to use a different base URL, the configuration will be slightly different:

<Location /octoprint/>
  RequestHeader set X-SCRIPT-NAME /octoprint/
  ProxyPassReverse http://<myOctoPrintHost>:5000/

  RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} =websocket [NC]
  RewriteRule /octoprint/(.*) ws://<myOctoPrintHost>/$1 [P,L]
  RewriteCond %{HTTP:UPGRADE} !=websocket [NC]
  RewriteRule /octoprint/(.*) http://<myOctoPrintHost>/$1 [P,L]
</Location>

If you also want to use https:

<Location /octoprint/>
  RequestHeader set X-SCRIPT-NAME /octoprint/
  RequestHeader set X-SCHEME https
  ProxyPassReverse http://<myOctoPrintHost>:5000/

  RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} =websocket [NC]
  RewriteRule /octoprint/(.*) ws://<myOctoPrintHost>/$1 [P,L]
  RewriteCond %{HTTP:UPGRADE} !=websocket [NC]
  RewriteRule /octoprint/(.*) http://<myOctoPrintHost>/$1 [P,L]
</Location>

#2

I have some questions. Am I correct in assuming that in your example nginx and octoprint are running on the same box?

I am trying to get nginx running on a 2nd box to rev-proxy my octopi box and while it is indeed working it is only proxying the HTML and im am kinda stuck as to why.


#3

Yes. If things are running on a different box, you'll have to substitute 127.0.0.1:5000 accordingly.


#4

Thank you for that. I assumed as much. I am still having issues - its like the java isnt getting through the proxy. All I am getting is straight HTML. Im sure I have overlooked something simple, but I for the life of me can not seem to figure out what it is.

This is what I am getting through nginx:


#5

Have you put it under a different base URL (eg /octoprint/)? If so, you need to tell OctoPrint about that so it can generate the correct URLs.

If not I'd suggest to check the network tab and the js error console, try to figure out from where it's trying to load stuff from which is failing and then cross reference that with my config.


#6
location /octo {
proxy_pass http://192.168.0.84/;
proxy_set_header Host $http_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-Scheme $scheme;
proxy_set_header X-Script-Name /octo;
proxy_http_version 1.1;
client_max_body_size 0;
}

This is what i got as a location block from octoprint. Im a bit confused about the rest.


#7

Try /octo/ instead of /octo. Maybe there's an issue with base URLs not ending in a slash - I have to admit that I never tested with those.


#8

Thank you very much for taking the time with this. Yes I realized with how old your original post was and had no comments that this might not be something others have done.

I am just sandboxing right now- but the plan is to have an nginx in the DMZ of my home network and use it as the jumping off point to everything - including my octoprint install.

So - the change you suggested did indeed bring me a lot closer to an answer.