Reverse proxy configuration

You mean what was mentioned in this post?

In fairness I would agree that the original post ought to be updated with the correct configuration for Haproxy 2.x and 1.x separately due to the breaking changes.

1 Like

All of the previous example code had a very different replacement regex for octoprint vs the web cam backends.

It was not at all obvious to me how to write that post replacement given the default version provided by OctoPi that I was starting with, and none of the existing posts (including the one you linked) provided working code.

That post is a wiki node :wink:

I'm not especially familiar with whatever I need to be familiar with for that to mean anything to me.

Can you suggest a resource that can explain to me what that means? Perhaps one that would make it clear what I should have done differently?

wiki posts are directly editable.so I think the idea was to edit the original, adding an haproxy 2 section maybe.

1 Like

Ah. Must be some sort of minimum post count or something, because I don't have an edit button.

It's ironic, because I would totally have quietly edited the OP but I can't because I have been quiet.

I am running HAProxy and the post with the full config file worked for me on Ubuntu 22.04. When I tried to add other pages written the same way as the web cam they are ‘not found’.l. Have Plex, home assistant, etc. etc. all on same server and would like to add this same convenience for everything as I am losing track of port numbers in my head. What am I missing?

Hello @Scott_Vanlandingham !

If you seeking for concrete help and trouble shooting, please open a new thread in Get Help Networking and provide all the information that is asked for.

My Bad! Will do!

1 Like

The fix I found in other post in the forums: "struggling to get reverse proxy working"
Enabling CORS under Settings > API and returning the npm configuration to "stock"

Thank you! Worked GREAT!!
The question I have though is... Why do I need this?
I log in using https, and the URL is the URL in the reverse proxy (op.theherrs.org {192.x.x.100})
And that proxies to "192.x.x.200" (the actual RasPi running OP).
My understanding is the source continues to look like op.theherrs.org the whole time.

Why is CORS needed?
(bigger question, why did it work for a couple of years until just now when I deployed on ProxMox VM??)

Here's a traefik docker-compose configuration where you access octoprint under a baseurl, important to strip the prefix with middleware:

version: "3.8"

services:
  octoprint:
    image: octoprint/octoprint
    labels:
      - "traefik.http.routers.octoprint.rule=Host(`example.org`) && PathPrefix(`/octoprint`)"
      - "traefik.http.routers.octoprint.entrypoints.websecure"
      - "traefik.http.routers.octoprint.tls=true"
      - "traefik.http.routers.octoprint.tls.certresolver=cloudflare"
      - "traefik.http.middlewares.octoprint-headers.headers.customrequestheaders.X-Script-Name=/octoprint"
      - "traefik.http.middlewares.octoprint-headers.headers.customrequestheaders.X-Scheme=https"
      - "traefik.http.middlewares.octoprint-strip-prefix.stripprefix.prefixes=/octoprint"
      - "traefik.http.routers.octoprint.middlewares=octoprint-headers,octoprint-strip-prefix"
      - "traefik.http.services.octoprint.loadbalancer.server.port=80"
    volumes:
     - octoprint:/octoprint

This was the smoking gun for me. Thanks for sharing.

In case someone is using Apache 2.4 (sudo apt info apache2) as the reverse proxy:
Reverse proxy configuration Apache2 for Octoprint using a wildcard cert

Also can't edit the Wiki post, but if anyone is having issues with Traefik websockets:

It appears Octoprint isn't handling schema wss provided by the X-Forwarded-Proto header (which is being added by Traefik by default). This causes Octoprint to reject the Web Socket request with a 403, with Firefox considering this a NS_ERROR_WEBSOCKET_CONNECTION_REFUSED error, aborting the web socket (which is slightly confusing, as it's obvious that a connection to Octoprint, through the reverse proxy, has been successfully made).

No specification disallows or allows for this schema, but wss isn't exactly orthodox (so I wouldn't go as far as calling this a bug, on either side).

Ultimately the fix is something like this:

http:
  middlewares:
    https-redirect:
      redirectScheme:
        scheme: https
    strip-camera-path:
      stripPrefix:
        prefixes:
          - "/camera-1"
    proto-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"

  routers:
    octoprint:
      rule: "Host(`octoprint.service.blah`)"
      service: octoprint
      middlewares:
        - https-redirect
        - proto-headers
    octoprint-inline-camera:
      rule: "Host(`octoprint.service.blah`) && Path(`/camera-1`)"
      service: octoprint-camera
      middlewares:
        - https-redirect
        - strip-camera-path

  services:
    octoprint:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8081"
    octoprint-camera:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"

The important section is the proto-headers middleware - used to override the wss schema to https.

http:
  middlewares:
    proto-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
...
  routers:
    octoprint:
      middlewares:
        - proto-headers

Basically, the /reverse_proxy_test/ test doesn't test web socket headers, so you'll silently have a really buggy UI when using Traefik with the default configuration.

I've followed the various advice here, with Traefik and Octoprint and NOTHING has worked. It's the only server/service on my network that I cannot figure out how to configure in Traefik. It should NOT be this hard.

I'm using the octoprint docker container with the mjpg-streamer, behind Traefik with the following config in my compose.yaml without any issues:

labels:
  traefik.enable: true
  traefik.http.routers.octoprint.entrypoints: web, websecure
  traefik.http.routers.octoprint.rule: Host(`octoprint.saturn.hye.network`) && !Path(`/webcam`)
  traefik.http.routers.octoprint.service: octoprint
  traefik.http.routers.octoprint.tls: true
  traefik.http.services.octoprint.loadbalancer.server.port: 5000

  traefik.http.routers.octoprint_cam.entrypoints: web, websecure
  traefik.http.routers.octoprint_cam.rule: Host(`octoprint.saturn.hye.network`) && Path(`/webcam`)
  traefik.http.routers.octoprint_cam.service: octoprint_cam
  traefik.http.routers.octoprint_cam.tls: true
  traefik.http.routers.octoprint_cam.middlewares: stripprefix_cam
  traefik.http.services.octoprint_cam.loadbalancer.server.port: 8080
  traefik.http.middlewares.stripprefix_cam.stripprefix.prefixes: "/webcam"

It's important to set the stream URL of the Classic Webcam plugin to /webcam?action=stream without the trailing slash after webcam.

I'm trying to switch my reverse proxy over from Nginx to Caddy (more specifically, caddy-docker-proxy). Nginx works properly, but when I try to proxy it with Caddy, it gives up with "socket connection failed." octoprint.log doesn't show any errors, but this error was logged by Caddy:

{"level":"error","ts":1729831392.5916576,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"am8.local:80","duration":0.015810937,"request":{"remote_ip":"192.168.1.1","remote_port":"50242","client_ip":"192.168.1.1","proto":"HTTP/2.0","method":"POST","host":"am8.alfter.us:1443","uri":"/sockjs/843/ctz1q3cw/xhr_streaming?t=1729831332571","headers":{"Accept-Language":["en-US,en;q=0.9"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Dnt":["1"],"Sec-Ch-Ua":["\"Not?A_Brand\";v=\"99\", \"Chromium\";v=\"130\""],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["https"],"Origin":["https://am8.alfter.us:1443"],"Priority":["u=1, i"],"Content-Length":["0"],"Sec-Fetch-Site":["same-origin"],"Accept":["*/*"],"Cookie":["REDACTED"],"Sec-Fetch-Mode":["cors"],"Sec-Ch-Ua-Platform":["\"Linux\""],"Sec-Ch-Ua-Mobile":["?0"],"X-Forwarded-For":["192.168.1.1"],"X-Forwarded-Host":["am8.alfter.us:1443"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"am8.alfter.us"}},"error":"reading: unexpected EOF"}

I'm using this docker-compose.yml to configure caddy-docker-proxy...since OctoPrint is actually running on a Raspberry Pi Compute Module 4 attached to the printer, I'm basically using a container that does nothing but configure the proxy:

services:
  am8:
    container_name: "am8"
    image: "busybox:uclibc"
    network_mode: none
    command: [ "tail", "-f", "/dev/null" ]
    labels:
      caddy: am8.alfter.us
      caddy.reverse_proxy: am8.local:80

I'm probably missing something in the Caddy config, but damned if I can figure it out.

Might be way off base here and I don't know anything about configuring Caddy but I would not expect you would point to port 80 if you did not have something additional in the route to port to 5000 which is what I would expect OctoPrint to be listening on.

Do you also have HAP installed on the compute module with OctoPrint? If not.. the OctoPrint install on your compute module should be listening on port 5000.

You can't connect to port 5000 in a standard OctoPi image, either connect to 80 or 443 which will forward to the port 5000 on the backend via haproxy running on the pi.