Reverse proxy

Household addresses must be served over HTTPS by a reverse proxy you control, such as Caddy, nginx, Nginx Proxy Manager or Traefik. JellyPass decides which household a request is for from its Host header, so the proxy's job is simple but strict.

What the proxy must do

DNS: point each household name, or a wildcard record such as *.example.com, at the proxy. Household names are a single label under your domain (jelly-grove.example.com), so one wildcard certificate covers them all; a wildcard certificate usually needs your proxy's DNS challenge.

Client addresses: TRUSTED_PROXIES and Jellyfin's known proxies

Behind a proxy every request reaches JellyPass from the proxy's address. Set TRUSTED_PROXIES to the address (or range) JellyPass sees the proxy connect from, so sign-in rate limits apply per client:

TRUSTED_PROXIES=192.168.1.5

With Docker's published ports this is often the Docker network's gateway address rather than 127.0.0.1; docker network inspect shows it. List only proxies you control: JellyPass walks X-Forwarded-For from right to left, skips trusted proxies and uses the first address it doesn't trust. Requests from addresses not listed are attributed to that address and their header is ignored.

JellyPass forwards to Jellyfin like any proxy hop. For Jellyfin to see real client addresses, add JellyPass and your reverse proxy in Jellyfin under Dashboard → Networking → Known proxies.

With a CDN in front of your proxy, either have the proxy restore the real client address from the CDN's header, or add the CDN's published ranges to both TRUSTED_PROXIES and Jellyfin's known proxies. Otherwise every client looks like a CDN server.

Examples

These are starting points, not complete configurations. Replace example.com, the household names and the LAN range with your own. Both were checked with Caddy 2.10 and nginx 1.28, including that a request naming any other host never reaches JellyPass.

Caddy

Caddy passes Host, handles WebSockets and streams responses by default, and gets certificates itself. Here Caddy shares a Docker network with JellyPass; list each household address:

# Household addresses: list each one.
jelly-grove.example.com, jelly-heath.example.com {
	reverse_proxy jellypass:8787
}

# The admin site: its own name, reachable from the LAN only.
jellypass-admin.example.com {
	@lan remote_ip 192.168.1.0/24
	handle @lan {
		reverse_proxy jellypass:8787
	}
	respond 403
}

nginx

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# Any other name: refuse it. Without this block the first server below
# would become the default and pass unmatched names to JellyPass, which
# answers any non-household name with the admin site.
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    ssl_reject_handshake on;
    return 444;
}

# Household addresses: jelly-<household>.example.com
server {
    listen 443 ssl;
    server_name ~^jelly-[a-z0-9-]+\.example\.com$;

    ssl_certificate     /etc/nginx/certs/wildcard.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/wildcard.example.com.key;

    location / {
        proxy_pass http://127.0.0.1:8787;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_buffering off;
        proxy_read_timeout 1h;
    }
}

# The admin site: its own name, LAN only.
server {
    listen 443 ssl;
    server_name jellypass-admin.example.com;

    ssl_certificate     /etc/nginx/certs/wildcard.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/wildcard.example.com.key;

    allow 192.168.1.0/24;
    deny  all;

    location / {
        proxy_pass http://127.0.0.1:8787;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
    }
}

If you use a different HOUSEHOLD_HOST_PREFIX, change jelly- in server_name to match. Keep the default_server block: nginx picks the server by the request's Host, not only by the name the TLS connection used, so a request naming any other host is closed instead of reaching the admin site. The Caddy example needs no such block: Caddy serves only the names listed and answers any other Host with an empty response, without passing it to JellyPass.

Nginx Proxy Manager and Traefik

The same rules apply: one proxy host (or router) per household name, or one that matches only your household pattern, pointing at JellyPass on port 8787 with WebSocket support on, and a separate, restricted host for the admin site. Nginx Proxy Manager passes Host unchanged; turn on Websockets Support for household hosts.