> ## Content Index
> Fetch the complete content index at: https://blog.uptime.bet/llms.txt
> Use this file to discover other available public pages before exploring further.

# Pocket ID: Passkey-Only Single Sign-On for Your Homelab with Docker Compose
- URL: https://blog.uptime.bet/pocket-id-self-hosted-passkey-sso-oidc-docker/
- Published: 2026-11-02T12:26:21.000Z
- Updated: 2026-11-02T12:26:21.000Z
- Description: Pocket ID is a small, OpenID Connect certified identity provider that only uses passkeys. Here is how to run v2.19 with Docker Compose, connect your first app and lock down who can sign in.
- Author: Alexandre Nebeling
- Tags: Self-Hosted, Security, Docker, Homelab, Open Source

Every self-hosted app comes with its own login page, its own user list and its own password. After the tenth service that gets old, and it is not great for security either. The classic fix is single sign-on (SSO) with an identity provider, but tools like Keycloak or Authentik can feel like running a second job.

**Pocket ID** takes a refreshingly simple approach: it is a small OpenID Connect (OIDC) provider that **only supports passkeys**. No passwords to leak, no TOTP codes to type. You sign in with Face ID, Windows Hello, your phone or a YubiKey, and every connected app trusts that login. In this guide we set up the current release **v2.19.1** (22 October 2026) with Docker Compose.

## What is Pocket ID?

Pocket ID describes itself as an easy-to-use, **OpenID Connect Certified** and OAuth 2.0 provider that lets users sign in to your applications with passkeys. It is written in Go with a Svelte frontend, released under the **BSD-2-Clause license**, and close to 10,000 stars on GitHub.

![Pocket ID sign-in page for an app, asking the user to authenticate with a passkey](https://blog.uptime.bet/content/images/2026/11/pocket-id-screenshot-light.webp)

The Pocket ID sign-in page: one button, one passkey, no password field. [Source: pocket-id/pocket-id repository](https://github.com/pocket-id/pocket-id?ref=blog.uptime.bet) (BSD-2-Clause)

The project is explicit about its goal: Keycloak and ORY Hydra exist, but they are often too complex for simple use cases. Pocket ID is a single program with a built-in SQLite database, so one container is all it needs.

## Key features

- **Passkey-only login** (WebAuthn), including hardware keys such as YubiKeys
- **Certified OIDC provider**, so it works with any app that supports "Login with OpenID Connect"
- **User groups** and per-app **allowed groups** to control who may sign in where
- **App dashboard** ("My Apps") so users see the services they can open
- **Audit log** of sign-ins with IP address and location
- **LDAP sync** and **SCIM** provisioning for larger setups
- **Community guides for close to a hundred apps**, including Immich, Jellyfin, Nextcloud, Proxmox, Paperless-ngx, Vaultwarden and Grafana

## What's new in recent releases

Pocket ID ships often. A few highlights from the last months:

- **v2.12.0** (July 2026) included security fixes and a **QR code sign-in** option. If you are on an older version, update.
- **v2.14.0** (August) added multiple client secrets per OIDC client and RFC 8414 authorization server metadata.
- **v2.17.0** (October) added **OIDC back-channel logout** and a redesigned client details page.
- **v2.18.0** (October) lets you search and pick client icons from the selfh.st icon library.
- **v2.19.0** (October) added configurable **login notifications**, an option to **force email verification**, searchable "My Apps" and the WebAuthn-recommended passkey algorithms. v2.19.1 updated Go and the base images.

## Before you start: HTTPS is required

Browsers only allow passkeys on HTTPS pages (or on `localhost` while testing). Passkeys are also bound to the domain, so pick the final address up front, for example `id.example.com`, and put a reverse proxy with a valid certificate in front of Pocket ID. Changing the domain later means your users have to register new passkeys.

## Installing Pocket ID with Docker Compose

### 1\. Get the files

```bash
mkdir -p /opt/pocket-id && cd /opt/pocket-id
curl -O https://raw.githubusercontent.com/pocket-id/pocket-id/v2/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/pocket-id/pocket-id/v2/.env.example

```

### 2\. Set the URL and encryption key

Pocket ID needs its public address and an encryption key. The example file recommends a file-based key:

```bash
openssl rand -base64 32 > encryption_key
chmod 600 encryption_key

```

```dotenv
# .env
APP_URL=https://id.example.com
TRUST_PROXY=false
PUID=1000
PGID=1000

```

The Compose file below mounts the key file into the container and sets `ENCRYPTION_KEY_FILE` to that path. Make sure the user from `PUID`/`PGID` can read it (`chown 1000:1000 encryption_key`). Alternatively you can put `ENCRYPTION_KEY=` with the generated value directly into `.env`. **Back up this key** together with the `data` folder; without it, encrypted data cannot be read.

### 3\. The Compose file with Traefik labels

```yaml
services:
  pocket-id:
    image: ghcr.io/pocket-id/pocket-id:v2.19.1
    container_name: pocket-id
    restart: unless-stopped
    env_file: .env
    environment:
      ENCRYPTION_KEY_FILE: /run/secrets/encryption_key
    volumes:
      - ./data:/app/data
      - ./encryption_key:/run/secrets/encryption_key:ro
    networks:
      - traefik
    labels:
      - traefik.enable=true
      - traefik.http.routers.pocket-id.rule=Host(`id.example.com`)
      - traefik.http.routers.pocket-id.entrypoints=websecure
      - traefik.http.routers.pocket-id.tls.certresolver=letsencrypt
      - traefik.http.services.pocket-id.loadbalancer.server.port=1411
    healthcheck:
      test: ["CMD", "/app/pocket-id", "healthcheck"]
      interval: 1m30s
      timeout: 5s
      retries: 2
      start_period: 10s

networks:
  traefik:
    external: true

```

The upstream file uses the floating `v2` tag; pinning a release makes updates a conscious decision. Images are published as `ghcr.io/pocket-id/pocket-id` and `pocketid/pocket-id` on Docker Hub.

Not using Traefik? Publish port `1411` and point Caddy or Nginx at it. The docs note that Nginx needs larger proxy buffers for Pocket ID, otherwise some pages fail with *502 Bad Gateway*.

```bash
docker compose up -d

```

### 4\. Show Pocket ID the real client IPs

Behind a proxy, every request seems to come from the proxy. Since Pocket ID logs sign-in IPs and rate-limits per IP, tell it which proxy to trust. `TRUST_PROXY` accepts `true`/`false` or a list of networks, for example the Docker network shared with Traefik:

```dotenv
TRUST_PROXY=172.18.0.0/16

```

Use your actual Docker network range (`docker network inspect traefik`). Behind Cloudflare, use `TRUSTED_PLATFORM=CF-Connecting-IP` instead.

### 5\. Create the admin account

Open `https://id.example.com/setup`, enter username, email and name, and register your first passkey. The setup page only works until the first account exists. If the browser refuses to create a passkey, the page is not on HTTPS or `APP_URL` does not match the address bar.

## Connecting your first app

Every app that signs in with Pocket ID is an **OIDC client**:

1. Find the app's **callback URL** (sometimes called redirect URI) in its OIDC docs.
2. In Pocket ID go to **Administration > OIDC Clients > Add OIDC Client**, enter a name and the callback URL. Apps with a backend are confidential clients; mobile, desktop and single-page apps are public clients and use PKCE.
3. Copy the **client ID** and **client secret**. The secret is only shown once.
4. In the app, enter the issuer `https://id.example.com` (discovery URL `https://id.example.com/.well-known/openid-configuration`), the client ID and the secret, with the scopes `openid profile email` (plus `groups` if the app maps roles from groups).

A nice real-world example is [Gotify 3](https://blog.uptime.bet/gotify-self-hosted-push-notifications-docker/), which added OIDC login this year and names Pocket ID in its docs. In Pocket ID, add the callbacks `https://gotify.example.com/auth/oidc/callback` and `gotify://oidc/callback` and enable PKCE. Gotify then only needs a few variables:

```dotenv
GOTIFY_OIDC_ENABLED=true
GOTIFY_OIDC_ISSUER=https://id.example.com
GOTIFY_OIDC_CLIENTID=<client id>
GOTIFY_OIDC_CLIENTSECRET=<client secret>
GOTIFY_OIDC_REDIRECTURL=https://gotify.example.com/auth/oidc/callback

```

The Pocket ID docs also have client guides for several tools we covered here, such as [Beszel](https://blog.uptime.bet/beszel-lightweight-server-monitoring-docker/), [BookStack](https://blog.uptime.bet/bookstack-self-hosted-wiki-docker/), [Healthchecks](https://blog.uptime.bet/healthchecks-self-hosted-cron-job-monitoring-docker/), [Karakeep](https://blog.uptime.bet/karakeep-self-hosted-bookmark-manager-docker/), [PatchMon](https://blog.uptime.bet/patchmon-self-hosted-linux-patch-management-docker/), [Termix](https://blog.uptime.bet/termix-self-hosted-ssh-server-management-docker/) and [Wallos](https://blog.uptime.bet/wallos-self-hosted-subscription-tracker-docker/).

## Decide who may sign in

Each OIDC client has an **Access** setting: either *all users* or only members of selected **user groups**. Create groups like `admins`, `family` and `media`, and allow only the right groups per app. Users outside those groups get "You are not allowed to access this service", and Pocket ID re-checks the groups on every token refresh, so removing someone from a group also removes their access.

## What about apps without OIDC?

Pocket ID only speaks OIDC. For apps without SSO support, put an **authentication proxy** in front of them that acts as the OIDC client, for example Tinyauth, OAuth2 Proxy, caddy-security or Traefik forward auth. The Pocket ID docs have examples for each.

## Tips from practice

- **Register two passkeys** per admin (for example phone and a YubiKey). If you lose your only passkey, follow the account recovery page in the docs.
- **Back up `data/` and the encryption key.** That is your whole identity provider.
- **Don't put the SQLite database on a network share.** Recent versions even warn about that in the admin UI.
- **Air-gapped?** `VERSION_CHECK_DISABLED=true`, `ANALYTICS_DISABLED=true` and `ICON_LIBRARY_URL=disabled` turn off the outgoing requests.
- **Keep it updated** and watch it with [Uptime Kuma](https://blog.uptime.bet/uptime-kuma-2-self-hosted-uptime-monitoring-docker/). If your identity provider is down, nobody can log in anywhere.

## Pocket ID vs Authentik, Authelia and Keycloak

|                | Pocket ID                   | Authentik                       | Authelia                         | Keycloak            |
| -------------- | --------------------------- | ------------------------------- | -------------------------------- | ------------------- |
| Focus          | Simple OIDC provider        | Full identity platform          | Forward-auth portal + OIDC       | Enterprise IAM      |
| Login          | Passkeys only               | Passwords, MFA, passkeys, flows | Passwords + 2FA (TOTP, WebAuthn) | Everything          |
| Footprint      | One small container, SQLite | Server, worker, PostgreSQL      | Small, file or DB config         | Java app + database |
| Learning curve | Low                         | High                            | Medium                           | High                |

If you want passwordless SSO for a handful of apps and don't need complex flows, Pocket ID is the easiest option by far. If you need password logins, LDAP as a source of truth or detailed policies, look at Authentik or Keycloak.

## Conclusion

Pocket ID turns SSO from a weekend project into a 15-minute job. Passkeys make the login both easier and safer than passwords, and the OIDC certification means most self-hosted apps just work. Start with one or two apps, add your family as users, and enjoy never typing a homelab password again.

## Sources

- [Pocket ID on GitHub](https://github.com/pocket-id/pocket-id?ref=blog.uptime.bet) (BSD-2-Clause license)
- [Pocket ID releases](https://github.com/pocket-id/pocket-id/releases?ref=blog.uptime.bet)
- [Pocket ID documentation](https://pocket-id.org/docs/introduction?ref=blog.uptime.bet): installation, reverse proxy, connect an app, allowed groups, authentication proxies, client examples
- [Gotify OIDC documentation](https://gotify.net/docs/oidc?ref=blog.uptime.bet)