Skip to content
Public template

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pocket ID on Render

A simple OpenID Connect provider that signs users in with passkeys. Add single sign-on to your self-hosted apps without passwords. This repo is the Blueprint. The app runs from the official Pocket ID image.

Deploy to Render

Render Upstream Pocket ID License

What This Template Shows

This repository does not contain the Pocket ID source. The service pulls the official image from Docker Hub at a pinned version. To upgrade, change the tag in render.yaml and push.

Piece Role
Pocket ID OIDC provider, admin UI, and passkey sign-in in one Go binary.
pocket-id (Web Service) The app.
pocket-id-db (Render Postgres) Users, passkeys, OIDC clients, and uploaded images.
pocket-id-data (Persistent disk) Caches only. It makes Render stop the old instance before starting a new one, which Pocket ID requires.

Architecture

flowchart LR
  user["Browser"] --> app["pocket-id"]
  apps["Your apps (OIDC clients)"] --> app
  app --> db[("pocket-id-db")]
  app -.->|caches| disk[("pocket-id-data")]
  hub["Docker Hub: pocketid/pocket-id:v2.19.2"] --> app
Loading

How It Works

  1. Click Deploy to Render. The flow copies this repo into your GitHub account and applies render.yaml.
  2. Render creates the database and generates ENCRYPTION_KEY. There is nothing to fill in.
  3. Pocket ID creates its tables in Postgres and starts.
  4. Open /setup and create the admin account with a passkey.
Resource Type Plan Notes
pocket-id Web, image Starter Disk at /app/data, 1 GB. Health: /healthz. Single instance.
pocket-id-db Postgres 16 Basic 256 MB Internal connections only. Also stores uploads (FILE_BACKEND=database).

Default region: Oregon.

Quick Start

  1. Click Deploy to Render above.
  2. Wait until pocket-id is Live.
  3. Right away, open https://<pocket-id>.onrender.com/setup and create the admin account. Until you do, anyone who opens that page can claim it.
  4. In the admin UI, add an OIDC client for each app you want to sign in to.
curl -fsS "https://<pocket-id>.onrender.com/healthz"

Important

Passkeys are bound to the domain in APP_URL. If you plan to use a custom domain, add it and update APP_URL before anyone registers a passkey. Passkeys made on the onrender.com domain stop working after the switch.

Migrating From Another Pocket ID

Pocket ID's export and import commands move all users, passkeys, OIDC clients, and settings. The import replaces the whole database, so skip /setup. Because the data lives in Postgres, you run the import from your old host, straight into pocket-id-db.

  1. On the old instance, export:

    docker exec pocket-id /app/pocket-id export --path - > pocket-id-export.zip

    The Render instance must run the same Pocket ID version as the old one, or a newer one. Check with /app/pocket-id version.

  2. On the pocket-id service's Environment page:

    • Set ENCRYPTION_KEY to the old instance's key. The export keeps secrets encrypted with it.
    • Set APP_URL to the old domain, then add that domain under Settings → Custom Domains. Passkeys and OIDC clients only work on the domain they were set up with.

    The service may fail to start after this, because its first boot encrypted a new signing key with the generated key. The import replaces that key.

  3. Suspend the pocket-id service. If it is running, Render restarts it during the import, and the restarted server writes to the database while the import is replacing it. The import then fails with duplicate key value violates unique constraint.

  4. On pocket-id-db, under Info → Access Control, allow your old host's public IP. Copy the External Database URL.

  5. On the old host, run the import with the same image version:

    docker run --rm -i \
      -e DB_CONNECTION_STRING='<External Database URL>' \
      -e ENCRYPTION_KEY='<old key>' \
      -e FILE_BACKEND=database \
      pocketid/pocket-id:v2.19.2 \
      /app/pocket-id import --path - --yes --forcefully-acquire-lock < pocket-id-export.zip

    --forcefully-acquire-lock clears any lock or registration a stopped instance left behind. Each query crosses the internet, so expect a minute or two. Wait for Import completed successfully.

  6. Resume the service, remove your IP from Access Control, then point the domain's DNS at Render.

If the import fails, keep the service suspended and run it again. The import clears the database first. A resumed service would start on the partial data and generate a new signing key.

Configuration

Variable Source Description
ENCRYPTION_KEY Generated Encrypts private keys and secrets in the database. Never change it.
APP_URL Wired The service's RENDER_EXTERNAL_URL. The OIDC issuer and passkey domain.
DB_CONNECTION_STRING Wired Internal URL of pocket-id-db.
FILE_BACKEND Blueprint database. Stores uploaded logos and profile pictures in Postgres, so database backups cover everything.
TRUST_PROXY Blueprint true. Reads client IPs from Render's proxy for audit logs and rate limiting.
PORT Blueprint 1411.
ANALYTICS_DISABLED Blueprint true. Turns off the anonymous instance heartbeat.
MAXMIND_LICENSE_KEY Optional Adds IP geolocation to audit logs. See .env.example.

generateValue runs once, on the first Blueprint apply. Email (SMTP) is configured in the admin UI, not with env vars.

Cost

Prices from Render's pricing page.

Resource Approx. monthly
pocket-id (Starter) $7
pocket-id-db (Basic 256 MB) $6
1 GB disk $0.25
Total ~$13.25

Troubleshooting

Problem Solution
Passkey sign-in fails after adding a custom domain Passkeys are bound to the old domain. Users must register new passkeys on the new domain.
OIDC clients reject the issuer APP_URL must match the URL the clients use. Update it after you add a custom domain.
First deploy fails to connect to Postgres The service started before pocket-id-db accepted connections. Wait for the database to be Available and click Manual Deploy.
Deploy fails with already one instance of Pocket ID running The disk is missing. Pocket ID can't overlap with the old instance during a deploy, and the disk makes Render stop the old one first.
Deploy takes about a minute of downtime Expected. A service with a disk stops the old instance before it starts the new one.

Project Structure

render.yaml       Blueprint. One image-backed web service with a disk, and Postgres.
README.md         This file
LICENSE           Wrapper license
.env.example      Optional extras

Learn More

License

MIT for this wrapper. Pocket ID is licensed under BSD-2-Clause.