Skip to content

Reverse proxy

xNifty edited this page Oct 11, 2026 · 2 revisions

Public URLs can stay at the site root or under a prefix such as /gotodo. Set BASE_PATH to that path only (no host), for example BASE_PATH=/gotodo.

Ordryn listens on 127.0.0.1 by default (HOST in Configuration), so a proxy on the same machine works without opening the port to the network.

The usual nginx pattern strips the prefix before Go. Build the SPA on the host after setting BASE_PATH:

cd web && rm -rf node_modules && npm ci && npm run build

(or npm run build:web from the repo root).

location /gotodo/ {
    proxy_pass http://127.0.0.1:9000/;  # strip /gotodo
    proxy_intercept_errors off;

    # Task attachments and images: at least the largest size allowed in Admin
    client_max_body_size 55m;

    proxy_http_version 1.1;
    proxy_set_header Host $host;
    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;

    # Live updates (SSE) and long MCP requests
    proxy_read_timeout 1h;
}

Do not turn on proxy_intercept_errors (or equivalent error_page rewriting) for this location. It replaces API JSON 400/401 responses with HTML.

Browser: /gotodo/… · Go receives: /… · the SPA still knows the public prefix via <meta name="gotodo-base">. The server rewrites Vite ./assets URLs to /gotodo/assets/… so nested routes work without a <base href> (which would break in-page # anchors).

Strip and preserve-prefix proxies can both work if BASE_PATH matches the public URL. For a subpath demo, set BASE_PATH=/gotodo and proxy /gotodo/ to the backend.

Upload size

nginx rejects request bodies over 1 MB by default with 413, before Ordryn sees them. Set client_max_body_size to at least the larger of Largest file (attachments) and Maximum image size in Admin-settings, plus a little room. Both can go up to 50 MB.

Live updates (SSE)

The web UI holds a long-lived GET /api/v2/events stream so boards and lists update without a refresh. Ordryn sends X-Accel-Buffering: no, which turns off nginx buffering for that response. Other proxies (Caddy, Traefik, Cloudflare, HAProxy) generally pass SSE through, but check that they:

  • don't buffer or compress text/event-stream responses,
  • don't close idle connections after a short timeout (raise read or idle timeouts to several minutes or more).

If changes from other users or tabs only show up after a reload, the stream is being buffered or cut.

HTTPS

Set USE_HTTPS=true when the site is served over TLS (cookie Secure flag). Terminate TLS at the proxy; Go can still listen on HTTP locally. Forward X-Forwarded-Proto so links Ordryn builds, such as the GitHub OAuth callback and device-login URLs, use https. Optionally set ENV=production to send an HSTS header.

Set PUBLIC_URL (for example https://todo.example.com/gotodo) so extension messages link back to the right place.

Contributor notes for the Vue app live in web/README.md.

Clone this wiki locally