DurinDoor
Deployment

Reverse proxy and static assets

Loopback proxy trust for X-Forwarded-For, static asset checks, nginx and Caddy.

Use this guide after DurinDoor responds on loopback. You need a working build, a public HTTPS origin, and nginx or Caddy on the same host.

Configure the public origin

Set BASE_URL and NEXT_PUBLIC_BASE_URL to the public HTTPS origin. Set AUTH_COOKIE_SECURE=true, restart the app, and verify login through that origin.

Configure forwarding headers

DurinDoor trusts the rightmost X-Forwarded-For value only when the TCP peer is loopback. Leftmost x-forwarded-for and x-real-ip are ignored because a client can send them. The wrapper then deletes x-forwarded-for, x-forwarded-host, and x-forwarded-proto before Next sees the request. Set BASE_URL and NEXT_PUBLIC_BASE_URL to the public HTTPS origin; the proto/host headers are not a substitute.

A proxy that is not on loopback relative to DurinDoor (host nginx to a Docker bridge IP, or Caddy in another Compose service) does not qualify for forwarding-header trust. DurinDoor then uses the socket peer address and ignores X-Forwarded-For. Keep DurinDoor on 127.0.0.1 and proxy to that port on the same host.

Overwrite X-Forwarded-For. Do not append.

nginx

location / {
  proxy_pass http://127.0.0.1:20128;
  proxy_http_version 1.1;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_read_timeout  600s;
  proxy_send_timeout  600s;
}

$remote_addr replaces any client-supplied chain. Long timeouts cover model streams.

Caddy

durindoor.example.com {
  reverse_proxy 127.0.0.1:20128 {
    header_up Host {host}
    header_up X-Forwarded-Proto {scheme}
    header_up X-Forwarded-For {remote_host}
    flush_interval -1
    transport http {
      read_timeout 600s
      write_timeout 600s
    }
  }
}

header_up X-Forwarded-For {remote_host} overwrites the header with the client DurinDoor should see. Caddy still terminates TLS; set AUTH_COOKIE_SECURE=true and the BASE_URL pair to this HTTPS origin.

TRUST_PROXY=true is a separate login-limiter switch. Only turn it on when this wrapper is in the path and the proxy overwrites forwarding headers. Details: Security.

Static assets

Next standalone tracing does not copy everything this repo needs at boot. npm run build copies custom-server.js, open-sse/, MITM sources, public/, and .next/static/ into .next/standalone/. Previous public/ and .next/static/ copies are removed first so an old hashed chunk cannot be served.

The Docker image does the same copy: public/ and .next/static/ land next to standalone. A custom image that drops those COPY lines 404s /_next/static/... and leaves the dashboard blank.

npm run verify:static

After npm run build:

npm run verify:static

The check starts .next/standalone/custom-server.js on a free 127.0.0.1 port, with a throwaway DATA_DIR and dummy JWT_SECRET / API_KEY_SECRET. It GETs /dashboard, parses local .js, .css, .woff2, .svg, .ico, .webmanifest, and .png URLs, and requires HTTP 200 for each. Missing assets print and the process exits non-zero. No JS/CSS in the HTML is also a failure.

A zero exit code confirms those assets are reachable in the checked build. It does not run browser interactions. If the check fails, rebuild before restarting, and inspect missing files in the packaged build. Run the check before deploying. Install choices: Laptop. Docker copies: Docker. VPS unit: VPS and cloud.

On this page

Edit on GitHub