Skip to content

Reverse Proxy and HTTPS

60plus edited this page Jul 11, 2026 · 3 revisions

Reverse Proxy & HTTPS

A reverse proxy is optional. GamesDownloader is designed to run LAN-only, over plain HTTP on port 8080, with no proxy and no domain, and that is a fully supported way to use it. You only need this page if you decide to expose the instance beyond your local network and want a domain name and HTTPS in front of it.

If you run GamesDownloader only on your LAN, skip this page. Securing the local network is the administrator's responsibility, and none of the settings below are required. See Network & Security for the LAN-friendly design.

Contents

How it fits together

GamesDownloader serves plain HTTP on container port 8080. A reverse proxy sits in front of it, terminates TLS (holds your certificate), and forwards requests to the app. The app never sees TLS directly; instead it relies on the proxy to tell it, through request headers, what the original client used:

  • Was the original request HTTPS? The proxy signals this with X-Forwarded-Proto. GamesDownloader only enables HSTS (the header that tells browsers to stick to HTTPS) when it sees X-Forwarded-Proto: https, so a LAN-only HTTP deployment is never locked into HTTPS by accident.
  • Who is the real client? The proxy passes the client address in X-Real-IP (and/or X-Forwarded-For), and GamesDownloader reads it - but only when the request actually arrived from a peer it trusts (see below). Brute-force protection is the control that consumes the trusted-proxies list you configure: it keys bans on the extracted real IP. The IP allowlist and audit logging use the same safe extraction logic but trust only private/LAN peers by default (they do not read the configured list), so keep your proxy on a private hop - or lock the origin down at the firewall - rather than relying on the trusted-proxies setting for them.

Because the app also uses Socket.IO for live progress (downloads, sync, scans, antivirus), the proxy must additionally allow WebSocket upgrades.

Three settings that matter behind a proxy

Settings → Security → Network & Access

Settings → Security → Network & Access

  1. Trusted proxies. GamesDownloader ignores forwarded headers from untrusted peers, so a client cannot spoof X-Real-IP to dodge a ban or the allowlist. When you put a proxy in front, add the proxy's address to the trusted-proxies list under Settings -> Security. Private/LAN peers are already treated as trusted; add the proxy explicitly if it reaches the app from a non-private address.
  2. Public base URL. Set Settings -> Security -> Public URL to your externally visible origin, for example https://games.example.com. GamesDownloader uses it to build absolute links in emails (such as password-reset links), so they always point at your real domain instead of being derived from a request header an attacker could tamper with.
  3. CORS origins. If you access the API from another origin, add it to the allowed CORS origins under Settings -> Security. For a single-origin proxy setup you normally do not need to change this.

All three are applied without a restart.

nginx / openresty example

A minimal HTTPS server block that terminates TLS and forwards to GamesDownloader running on the same host (adjust server_name, certificate paths, and the upstream address):

server {
    listen 443 ssl;
    server_name games.example.com;

    ssl_certificate     /etc/ssl/games.example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/games.example.com/privkey.pem;

    # Large game and ROM uploads: raise or disable the body size limit.
    client_max_body_size 0;

    location / {
        proxy_pass http://127.0.0.1:8080;

        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;   # lets the app know it is HTTPS

        # WebSocket upgrade for Socket.IO live progress
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Long-lived downloads and streams
        proxy_read_timeout 3600s;
        proxy_buffering off;
    }
}

# Optional: redirect plain HTTP to HTTPS
server {
    listen 80;
    server_name games.example.com;
    return 301 https://$host$request_uri;
}

The three X-Forwarded-* / X-Real-IP headers are the important part: without X-Forwarded-Proto the app will not treat the connection as secure (no HSTS), and without X-Real-IP brute-force protection would see every request as coming from the proxy.

client_max_body_size defaults to 1 MB in nginx and will reject large uploads with a 413 error. Set it to 0 (unlimited) or a high value if you upload big game files or ROM sets through the web UI. GamesDownloader enforces its own upload size limit separately.

Caddy example

Caddy obtains and renews TLS certificates automatically and sets the forwarding headers for you, which makes it the shortest correct configuration:

games.example.com {
    reverse_proxy 127.0.0.1:8080
    request_body {
        max_size 0
    }
}

Caddy's reverse_proxy sets X-Forwarded-Proto, X-Forwarded-For, and handles WebSocket upgrades by default.

Cloudflare

If you put Cloudflare in front, the real client address arrives in CF-Connecting-IP, which GamesDownloader understands. The brute-force and allowlist logic is Cloudflare-aware, but it still only trusts that header when the request reaches the app from a trusted upstream, so keep your origin locked down (for example, only accept connections from Cloudflare's ranges at the firewall or origin proxy). Enabling Cloudflare's "Always Use HTTPS" pairs well with the app's HSTS behaviour.

Verifying it works

  • Browse to your domain over HTTPS and confirm the padlock.
  • Check that the app reports the response as secure: an HTTPS load should include an Strict-Transport-Security header (visible in your browser's network tab). If it is missing, your proxy is probably not sending X-Forwarded-Proto: https.
  • Trigger one failed login, then confirm in the audit log / security tooling that the recorded IP is the real client, not the proxy. If every event shows the proxy's address, the proxy is not sending X-Real-IP, or it is not in the trusted-proxies list. See Network & Security.
  • Request a password reset and confirm the link in the email points at your public domain (this needs SMTP configured and the Public base URL set).

Next: Network & Security - Configuration

Clone this wiki locally