osrs-data-hub

Reverse proxy

The proxy settings the hub depends on, with Caddy and nginx examples.

Terminate TLS in the proxy you already run and forward to 127.0.0.1:3000. The hub relies on six things from it.

  1. Don't buffer text/event-stream. The live stream (/api/live/stream) sends X-Accel-Buffering: no, which nginx honours. Caddy and Traefik stream by default.
  2. Forward the host and client address. Keep the original Host (or set X-Forwarded-Host), and append the client address to X-Forwarded-For. See Client addresses.
  3. Serve the hub over HTTPS. Some same-origin checks rely on Sec-Fetch-Site, which browsers send only to secure origins. On plain http://<LAN address>, the data export and the raw-payload viewer answer 403.
  4. Leave /api/v1/* alone. Don't add CORS or caching headers in the proxy. The hub sets Access-Control-Allow-Origin: *, ETag and Cache-Control itself.
  5. Never redirect /api/osrs-data/*. The plugin turns a 301 or 302 into a body-less GET and doesn't follow 307 or 308, so data is lost without any error. Redirect http to https for the UI only, or tell players to use the https:// URL exactly as the wizard shows it.
  6. Keep /metrics off the internet. It is token-protected, but only your monitoring needs it: answer 404 to everyone else.

Examples

Caddyfile
hub.example.com {
  # /metrics only for the Prometheus server (drop the allow-list to block it entirely).
  @metrics_blocked {
    path /metrics /metrics/*
    not remote_ip 10.0.0.5
  }
  respond @metrics_blocked 404
  reverse_proxy 127.0.0.1:3000
}

Client addresses

The hub rate-limits pairing and failed API authentications per client IP. To find the client's address, it reads X-Forwarded-For, counting TRUST_PROXY_HOPS entries from the right: one per proxy that appends to the header.

SetupTRUST_PROXY_HOPS
One proxy on the VM (Caddy, nginx)1 (the default)
Cloudflare → cloudflared → Traefik2
Nothing in front of the hub0

Get this number right

Too low, and every client looks like your proxy: one integration with a bad key then locks every API client out for about a minute. Too high, and the hub trusts an address the client wrote itself.

On this page