Skip to content

Reverse Proxy

Weaver can run at a domain root or under a URL subpath. If you use a subpath, configure both Weaver and the proxy with the same base URL.

Native installs listen on 127.0.0.1, which a proxy on another host can’t reach:

  • Container. Nothing to do. The image listens on 0.0.0.0, so a proxy in another container or on the host reaches it through the Docker network or the published port.
  • Proxy on the same host as a native install. Nothing to do. The proxy connects over loopback.
  • Proxy on a different host from a native install. Set Listen address in Settings → Security → Network access to 0.0.0.0, or to the interface the proxy connects over, and restart Weaver. WEAVER_HTTP_BIND_ADDRESS does the same from the environment.

Without this step, Weaver sees every request as coming from the proxy. Sign-in still works, but Weaver can’t tell browsers apart, can’t see that the browser used HTTPS, and can’t match Remembered-session CIDRs against real addresses.

Add the proxy’s address, or a narrow CIDR around it, under Trusted proxy addresses or CIDRs in Settings → Security → Network access. It applies as soon as you save.

To manage it from the deployment instead, set WEAVER_TRUSTED_PROXIES, which also makes the field read-only. Separate entries with commas. A typo stops startup, so a mistyped entry is never silently skipped:

services:
weaver:
environment:
WEAVER_TRUSTED_PROXIES: 172.20.0.5

Setting the variable also makes first-run setup ask for the one-time setup code. A proxy saved in Settings doesn’t.

For requests from a trusted proxy, Weaver:

  • reads the browser’s address from X-Forwarded-For. It removes trusted hops from the right-hand end and takes the rightmost address left, which is the one your proxy recorded. A client can’t forge its way past that by adding addresses of its own on the left.
  • marks the session cookie Secure when X-Forwarded-Proto is https. The header must hold exactly one value, http or https. Anything else, including a comma-separated list, is refused with 403 invalid proxy protocol header.

Forwarding headers from any other address are ignored. Trust only proxies you run, and never a Docker gateway or a whole private range. Anything that can connect from a trusted address can claim to be any browser.

Your proxy must also:

  • Pass Origin through unchanged. A sign-in without exactly one valid Origin is refused with 403 a single valid Origin is required, and a session only works from the origin it signed in at.
  • Set X-Forwarded-For. Without it, Weaver can’t resolve the browser’s address, and browsers behind the proxy can’t be remembered.
  • Send one X-Forwarded-Proto when it terminates TLS.
  • Pass Host through, or send X-Forwarded-Host. Live updates run over a WebSocket, and Weaver refuses one whose Origin doesn’t match the host the request arrived at. A proxy that rewrites Host to Weaver’s own address, which nginx does by default, breaks that unless it also forwards the public name. If you can’t change the proxy, list the public name in WEAVER_HTTP_ALLOWED_HOSTS instead.

Some proxies send the forwarding headers by default. In nginx, add them with proxy_set_header Host $host;, proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; and proxy_set_header X-Forwarded-Proto $scheme;.

Weaver answers any hostname, so neither the public name nor a Docker service name like weaver needs to be listed.

To answer only known names, set WEAVER_HTTP_ALLOWED_HOSTS. Weaver then refuses every other name with 421 request Host is not allowed, apart from localhost and plain IP addresses. List every name that reaches Weaver, such as the Docker service name other containers use and the public name the proxy forwards:

services:
weaver:
environment:
WEAVER_HTTP_ALLOWED_HOSTS: weaver,weaver.example.com

Use hostnames only, without https:// or a path, separated by commas. An entry with a scheme, path, or wildcard stops startup, and so does an empty entry from a stray comma.

Matching is exact and ignores case. A subdomain is a different name, so weaver.example.com doesn’t cover weaver.lan.example.com. An entry with :port, such as weaver:9090, matches only that port and refuses a Host without one. A browser reaching the proxy over HTTPS sends no port, so leave the port off the public hostname unless you mean to require one.

After changing the environment, run docker compose up -d to recreate the container. Restarting the container doesn’t apply a changed environment.

To host Weaver at a subpath like https://example.com/weaver/, add a command override:

services:
weaver:
image: ghcr.io/scryer-media/weaver:latest
command: ["--config", "/config", "serve", "--port", "9090", "--base-url", "/weaver"]
ports:
- "9090:9090"
volumes:
- weaver-config:/config
- /path/to/downloads:/downloads

Then configure your reverse proxy to forward /weaver/ to Weaver.

  • Preserve the /weaver base path end to end.
  • Terminate TLS at the proxy.
  • Keep WebSocket support enabled if your proxy requires it explicitly.
  • Keep /graphql, /graphql/ws, assets, and app routes under the same base path.
  • Keep /metrics private unless it is intentionally exposed to your monitoring system.
  • Missing CSS or JavaScript usually means the base URL and proxy path disagree.
  • Broken live updates usually means WebSocket forwarding is missing, or the proxy rewrites Host without sending X-Forwarded-Host. Weaver logs refused a GraphQL socket opened from another origin in that case. Pass Host through, or list the public name in WEAVER_HTTP_ALLOWED_HOSTS.
  • 403 a single valid Origin is required at sign-in means the proxy dropped or rewrote the Origin header.
  • 403 browser verification required after a successful sign-in means the Origin header changed since sign-in, or a remembered browser now connects from an address outside Remembered-session CIDRs. Sign in again from the address you use.
  • 403 invalid proxy protocol header means a trusted proxy sent X-Forwarded-Proto more than once, as a list, or with a value other than http or https.
  • Current connection in Settings → Security → Network access shows the proxy’s address as the resolved client: the proxy isn’t under Trusted proxy addresses or CIDRs.
  • request Host is not allowed means WEAVER_HTTP_ALLOWED_HOSTS is set and doesn’t list that name. Add it or remove the variable, then recreate the container.
  • Security And Access explains the listen address, trusted proxies, remembered sessions, and signing in.
  • Configuration lists WEAVER_HTTP_ALLOWED_HOSTS, WEAVER_SECURE_COOKIES, and WEAVER_CORS_ALLOWED_ORIGINS.
  • API And Metrics covers the endpoints a proxy must forward.