When going to docs.example.com, I expect to be able to access and log into my HedgeDoc instance.
HedgeDoc is running in a Portainer stack (docker compose). I am accessing it via HAProxy - I’m connecting to the frontend with HTTPS, and HAProxy is communicating with HedgeDoc via HTTP.
What actually happened:
I can access docs.example.com. When I click “sign in”, the login window pops up. I enter email/password configured by the CLI user manager; when I click “sign in” in the box, the box simply disappears. If I click “new guest note”, it shows in the top right corner that I am offline.
There are no errors in the HedgeDoc logs or the browser console.
If I change CMD_PROTOCOL_USESSL to false, CMD_URL_ADDPORT to true, and CMD_DOMAIN to the machine’s local IP address, I can access and use hedgedoc at its IP:port.
I already tried:
I’ve played around with the environment variables - accessing the backend via HTTPS, moving it to a different port, and different values of CMD_PORT, CMD_HOST, CMD_HSTS_ENABLE, etc.
I have a feeling the issue is related to the following sentence in the docs: “The reverse proxy must allow websocket Upgrade requests at path /sockets.io/.” However, I can’t figure out how to check on this.
Finally figured it out! In pfSense, in the HAProxy frontend advanced settings, there’s a checkbox titled “Use ‘forwardfor’ option”. I recalled that I’d seen similar language in the example Nginx/Apache configs, so I tried enabling it and it did the trick.
It might be obvious to someone who knows Nginx/Apache or who is more experienced with networking in general, but it was total blind luck that I figured this out. It would be hugely helpful to update the docs to indicate that the reverse proxy must pass on the “X-Forwarded-For” header, and it would be useful to point out the existence of this option in HAProxy (though I know many use HAProxy outside of pfSense where they are working with text configurations rather than a GUI).
For anyone else using HAProxy, here are sanitized versions of my configs:
HAProxy:
frontend haproxy_bind
bind 172.20.0.99:443 name 172.20.0.99:443 ssl crt-list /var/etc/haproxy/haproxy_bind.crt_list
bind 172.20.0.99:80 name 172.20.0.99:80
mode http
log global
option http-keep-alive
option forwardfor
acl https ssl_fc
http-request set-header X-Forwarded-Proto http if !https
http-request set-header X-Forwarded-Proto https if https
timeout client 30000
acl https dst_port 443
acl docs var(txn.txnhost) -m beg -i docs.
acl aclcrt_haproxy_bind var(txn.txnhost) -m reg -i ^example\.com(:([0-9]){1,5})?$
acl aclcrt_haproxy_bind var(txn.txnhost) -m reg -i ^([^\.]*)\.example\.com(:([0-9]){1,5})?$
http-request set-var(txn.txnhost) hdr(host)
use_backend hedgedoc_ipvANY if docs https aclcrt_haproxy_bind
backend hedgedoc_ipvANY
mode http
id 121
log global
timeout connect 30000
timeout server 30000
retries 3
server servername 172.20.0.6:3002 id 117
For completeness, here’s the relevant snippets from my haproxy.conf to do TLS termination and then proxy to hedgedoc running in a container, on a dedicated subdomain: