Skip to content
v2.17.0GitHub

Reverse proxy

Serve Pocket ID over HTTPS with Caddy, nginx, Traefik or a Cloudflare Tunnel, and let it see your users' real IP addresses.

Browsers only create and use passkeys in a secure context, so Pocket ID has to be served over HTTPS, except when you open it at localhost. Pocket ID listens on plain HTTP on port 1411, and a reverse proxy in front of it adds the HTTPS.

Your serverBrowserssign-in and admin UIYour appstokens and user infoReverse proxyCaddy, nginx, Traefik…id.example.com:443Pocket IDlistens on port 1411Datadatabase and uploadsHTTPSHTTPSHTTP
Browsers and the apps you connect both reach Pocket ID at its public HTTPS URL, which is APP_URL. The proxy terminates TLS and forwards every path to port 1411.

Point a domain such as id.example.com at your server, then set it as the public URL in your .env file:

.env
APP_URL=https://id.example.com

APP_URL has to be the exact address you open Pocket ID at. Passkeys are bound to its domain, and Pocket ID builds every URL it hands to your apps from it.

Caddy fetches a certificate for the domain on its own:

Caddyfile
id.example.com {
reverse_proxy pocket-id:1411
}

pocket-id:1411 works when Caddy runs in the same Docker network as Pocket ID. For Caddy on the host, use localhost:1411.

Pocket ID records the IP address and location of each sign-in in the audit log, and its rate limits count requests per IP address. Behind a proxy, every request comes from the proxy’s address, so tell Pocket ID which proxies it can trust to pass the real one on:

.env
# The address or network of the proxy, such as the Docker network it shares with Pocket ID
TRUST_PROXY=172.18.0.0/16

Behind Cloudflare, read the address from the header Cloudflare sets instead:

.env
TRUSTED_PLATFORM=CF-Connecting-IP

Environment variables explains both options, and PROXY_PROTOCOL for load balancers that send the PROXY protocol.

Open https://id.example.com and create your admin account on /setup, as Installation describes. If your browser refuses to create the passkey, the page isn’t served over HTTPS or APP_URL doesn’t match the address in the address bar.