Railway

Deploy Pocket ID — Passkey-Only OIDC Provider

Self-host Pocket ID — passwordless passkey SSO for your apps

Deploy Pocket ID — Passkey-Only OIDC Provider

Just deployed

/app/data

Deploy and Host Pocket ID on Railway

Pocket ID is a simple, self-hosted OIDC provider built entirely around passkeys — no passwords, no TOTP codes, no external dependencies. Add single sign-on to your self-hosted services and sign in everywhere with a WebAuthn passkey or a hardware key like a YubiKey. It's the lightweight, passwordless alternative to heavier identity providers like Keycloak and Authentik, designed for people who want one modern login across their apps without running a complex platform. This template deploys it as a single container with the WebAuthn-critical settings handled.


What This Template Deploys

ServicePurpose
Pocket IDThe passkey-based OIDC provider, admin UI, and API on port 1411

A single, lightweight Go container backed by SQLite — no external database to manage. Everything (the database, uploads, and GeoLite2 IP data) lives under one /app/data volume, so the whole identity provider is one service with one volume.


About Hosting

Pocket ID is genuinely simple to run, but passkeys make one setting unusually strict — get it right and there's almost nothing else to configure.

APP_URL must exactly match your browser-facing URL — passkeys depend on it. Pocket ID puts APP_URL in three places: the OIDC issuer, the cookie domain, and — critically — the WebAuthn relying-party ID. Passkeys are cryptographically bound to that relying-party domain, so if APP_URL doesn't exactly match the URL users visit, passkeys won't register or verify at all, and because there are no passwords, there's no fallback. Set it to your exact Railway public domain before you run the first-time setup, and don't change it afterward.

TRUST_PROXY=true is required on Railway, and HTTPS is mandatory. WebAuthn only works in a secure (HTTPS) context, which Railway provides automatically. But Pocket ID runs behind Railway's proxy, so TRUST_PROXY=true must be set or it misreads the request protocol and origin, and passkey checks fail. This template sets it.

Claim your admin passkey immediately — the setup page is first-come. On first deploy, visit /setup and register your admin passkey right away. Whoever reaches /setup first becomes the administrator, so do this the moment the service is live, before the URL is exposed to anyone else.

ENCRYPTION_KEY protects sensitive data — pin it. Generate it with openssl rand -base64 32 (at least 16 bytes), set it once, and keep it stable. Combined with the /app/data volume, that keeps your identity provider intact across redeploys.

Typical cost: ~$5/month on Railway for the single lightweight container. Pocket ID is open source and free, and OpenID Connect Certified.


How It Compares

Pocket ID (passkey-only)Authentik / KeycloakAuth0 / OktaPassword + TOTP apps
AuthenticationPasskeys only (WebAuthn)Many methodsMany methodsPassword + 2FA
ComplexityVery lowHighManagedVaries
PasswordlessFullyOptionalOptionalNo
DependenciesSQLite onlyPostgres (+Redis)VendorVaries
Best forHomelab / simple SSOEnterprise IdPManaged SSOLegacy auth
Self-hostableYesYesNoVaries

Authentik and Keycloak are powerful but heavy for a handful of services. Auth0 and Okta are managed and per-user priced. Pocket ID's niche is deliberate simplicity: a single-container, passkey-only OIDC provider that gives your self-hosted apps modern passwordless SSO without the operational weight — ideal for homelabs and small teams that just want one secure login.


Deploy in Under 5 Minutes

  1. Click Deploy on Railway — Pocket ID builds automatically (~2 minutes)
  2. Set APP_URL to your exact Railway public domain (this is critical for passkeys)
  3. Confirm TRUST_PROXY=true, ENCRYPTION_KEY is set, and the /app/data volume is mounted
  4. Immediately visit /setup and register your admin passkey before anyone else can
  5. In the admin UI, add OIDC clients for your services and point each app at Pocket ID's discovery URL

Each connected app gets an OIDC client with callback URLs; your users then sign in with a passkey.


Common Use Cases

  • Unified homelab SSO — one passkey login across Grafana, Immich, Nextcloud, Gitea, Proxmox, and other OIDC apps
  • Passwordless authentication — eliminate passwords entirely using WebAuthn passkeys and hardware keys
  • YubiKey / hardware-key login — sign in to all your services with a physical security key
  • Simple SSO without the weight — get single sign-on without running Keycloak or a multi-service identity platform
  • Protect apps with no native auth — pair with a proxy like OAuth2-Proxy to gate services that lack OIDC support

Configuration

VariableRequiredDescription
APP_URLRequiredYour exact Railway public domain — used for OIDC issuer, cookies, and the WebAuthn relying party
ENCRYPTION_KEYRequiredEncrypts sensitive data — openssl rand -base64 32 (≥16 bytes), keep stable
TRUST_PROXYRequiredtrue — required behind Railway's HTTPS proxy for correct origin handling
MAXMIND_LICENSE_KEYOptionalFor GeoLite2 IP data used in login location display
PUID / PGIDOptionalUser/group IDs for the data volume if running non-root

APP_URL must match exactly, or passkeys break. It's baked into the WebAuthn relying-party ID, so a mismatch means passkeys won't register or verify — with no password fallback. Set it to your real Railway domain before first setup and keep it fixed.

Set TRUST_PROXY=true and claim /setup first. WebAuthn needs the correct HTTPS origin, which requires trusting Railway's proxy. And whoever visits /setup first becomes admin — register your admin passkey the moment the service is live.


Dependencies for Pocket ID Hosting

  • Railway account — Hobby plan (~$5/month) runs the single container
  • A persistent Railway volume mounted at /app/data (included)
  • A passkey-capable device or hardware key (YubiKey, phone, laptop biometrics)
  • OIDC-compatible apps to connect (most self-hosted services support OIDC)

Deployment Dependencies

Implementation Details

The template runs ghcr.io/pocket-id/pocket-id on port 1411 with a persistent volume at /app/data, which holds the SQLite database, uploads, and the GeoLite2 IP database — no external database is required. The app is a single Go binary, and Railway provides the automatic HTTPS that WebAuthn mandates.

APP_URL is the linchpin: Pocket ID writes it into the OIDC issuer identifier, the cookie domain, and the WebAuthn relying-party ID. Because passkeys are bound to the relying-party domain, APP_URL must exactly match the URL users load, or registration and verification fail with no password fallback. TRUST_PROXY=true is set so Pocket ID correctly derives the external HTTPS origin from Railway's proxy headers, and ENCRYPTION_KEY encrypts sensitive stored data and must remain stable across redeploys.

Administration is passkey-secured from the start: the first visitor to /setup registers the admin passkey and claims the instance, after which OIDC clients are added through the admin UI — each with a launch URL and callback URLs — and connected services authenticate against Pocket ID's OIDC discovery endpoint.


Frequently Asked Questions

Why must APP_URL be exact? It's used as the WebAuthn relying-party ID, and passkeys are cryptographically bound to that domain. If APP_URL doesn't match the URL users visit, passkeys won't register or verify — and since there are no passwords, there's no way in. Set it correctly before first setup.

What if I lose access to my passkey? Register more than one passkey (e.g. a hardware key plus a device) so you have a backup. Since Pocket ID is passwordless, keeping a second passkey enrolled is the recovery path.

Do I need a database? No external one. Pocket ID uses SQLite stored on the /app/data volume, so it's a single container with a single volume — part of what makes it so simple.

Why TRUST_PROXY=true? Railway terminates HTTPS with a proxy in front of Pocket ID. WebAuthn needs the correct secure origin, so Pocket ID must trust the proxy's forwarded headers, or passkey checks fail.

How do I connect my apps? In the admin UI, add an OIDC client for each app with its callback URLs, then point the app at Pocket ID's OIDC discovery URL. Most self-hosted services (Grafana, Immich, Nextcloud, and more) support OIDC.

Can I protect apps that don't support OIDC? Yes, by pairing Pocket ID with an auth proxy like OAuth2-Proxy, which authenticates against Pocket ID and gates services that have no native OIDC support.

Is it really passwordless? Completely. Pocket ID supports only passkeys — WebAuthn/FIDO2 — so there are no passwords to store, phish, or leak. That's the entire point.


Why Deploy Pocket ID on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Pocket ID on Railway you get modern passwordless SSO with the tricky parts solved — APP_URL and TRUST_PROXY set for WebAuthn, the /app/data volume for persistence, and automatic HTTPS. One passkey login across all your self-hosted services, on infrastructure you own.


Template Content

More templates in this category

View Template
Keycloak
Keycloak template with keywind theme + apple and discord providers

beuz
750
View Template
lua-protector
Test deployed my project first

trianaq765-cmd's Project
31
View Template
bknd
Feature-rich yet lightweight backend

10