Application Infrastructure AWS

Pocket ID Passwordless OIDC Provider on AWS User Guide

| Product: Pocket ID Passwordless OIDC Provider

Overview

This AMI runs Pocket ID 2.11.0 on Ubuntu 24.04 LTS. Pocket ID is a simple, self hosted OpenID Connect provider whose defining idea is that it authenticates people with passkeys rather than passwords. You point your existing applications at it as their identity provider, and your users sign in to all of them with the fingerprint reader, face unlock or hardware security key they already carry. There are no passwords to choose, rotate, leak or phish.

It ships as a single self contained Go binary that embeds its own web interface and stores everything in an embedded SQLite database, so the whole identity plane is one process and one file. That makes it a genuinely practical alternative to running a large identity suite when what you actually need is OIDC single sign on for a handful of self hosted applications.

Secure by default, with no admin hijack window. Pocket ID's initial admin setup route is open to whoever reaches it first while no user exists yet. On a fresh public IP that is a real risk: this is your identity provider, so whoever claims it owns every application behind it. This AMI therefore ships with no user, no passkey, no signing key and no secret at all, and pocket-id-firstboot.service creates the sole admin for your instance specifically during first boot, which closes the setup route before the instance is ever reachable. That admin has no password and no passkey. The only way in is a one time sign in link that exists solely on your instance in a root only file, or a fresh one you mint over SSH. Your SSH key is the root of trust.

What is included:

  • Pocket ID 2.11.0, installed from the official upstream release binary and verified against the release's own published checksum
  • Pocket ID listening on 127.0.0.1:1411, loopback only, so it is never exposed directly
  • nginx on port 80 reverse proxying the interface, plus an unauthenticated /healthz endpoint for load balancer health probes
  • A per instance admin account and one time sign in link generated on first boot and recorded at /root/pocket-id-credentials.txt (mode 0600)
  • A per instance encryption key generated on first boot, so no two instances ever share one
  • pocket-id.service, nginx.service and a one shot pocket-id-firstboot.service as systemd units, enabled and active
  • pocket-id-admin-link and pocket-id-set-url helper commands
  • A fully patched Ubuntu 24.04 LTS base with unattended security upgrades enabled
  • 24/7 cloudimg support

Prerequisites

An AWS account, an EC2 key pair in the target region, and a VPC with a public subnet. m5.large (2 vCPU / 8 GiB RAM) is the recommended instance type, though Pocket ID is a single lightweight Go process and runs comfortably. Security group inbound: allow 22/tcp from your management network and 80/tcp (plus 443/tcp once you add TLS). Port 1411 never needs opening because Pocket ID binds to loopback and is reached only through nginx.

You will need a DNS name. This is the one thing to plan for before you start. Passkeys are built on the WebAuthn standard, which requires a secure context (HTTPS) and a registrable domain as the relying party identifier. A bare IP address is not a valid relying party identifier, so a passkey cannot be registered against http://<instance-ip>/ in any browser. The instance comes up fully working on its IP address and you can sign in and configure it there, but to register passkeys and run this for real you need a domain name and a certificate. Step 7 covers that.

Connecting to your instance

SSH to the instance as the default login user for the AMI variant you launched, using the EC2 key pair you selected at launch:

AMI variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i /path/to/key.pem ubuntu@<instance-public-ip>

Step 1 - Launch from the AWS Marketplace

Find Pocket ID by cloudimg in the AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration and Continue to Launch. Pick your region, the m5.large instance type, your VPC subnet and EC2 key pair. For the security group, allow SSH (22) from your IP and HTTP (80) from where your users will reach it. Launch the instance.

Step 2 - Confirm the services are running

All three units should report active, and Pocket ID itself should be listening on 127.0.0.1:1411 only, with nginx on port 80.

systemctl is-active pocket-id pocket-id-firstboot nginx
sudo ss -tlnp | grep -E ':80 |:1411 '

Step 3 - Retrieve your one time admin sign in link

First boot created the sole admin for this instance and minted a one time sign in link for it. The link is single use and expires one hour after first boot.

sudo ls -l /root/pocket-id-credentials.txt

The file is root owned and mode 0600. It looks like this, with the token shown masked here:

POCKET_ID_URL=http://<instance-ip>/
POCKET_ID_ADMIN_USERNAME=admin
POCKET_ID_ADMIN_SIGNIN_LINK=<POCKET_ID_ADMIN_LINK>

If the link has expired, or you simply want a fresh one, mint another at any time. This is upstream's own admin recovery path, and it is the reason a lost passkey can never lock you out of your own identity provider:

sudo pocket-id-admin-link

Step 4 - Confirm the provider is serving

The health endpoint answers, and the OIDC discovery document reports the issuer your applications will use plus the grant types the provider supports.

curl -sI http://127.0.0.1/healthz | head -1
curl -s http://127.0.0.1/.well-known/openid-configuration | jq -r '.issuer'
curl -s http://127.0.0.1/.well-known/openid-configuration | jq -r '.grant_types_supported[]'

Step 5 - Confirm no credential shipped in the image

This is worth verifying yourself, because it is the whole security argument for running an identity provider from a prebuilt image.

The initial admin setup route returns 404, meaning the admin was already created for this instance and nobody else can claim it. The API rejects unauthenticated callers with 401. And the passkey table is empty, because no passkey ships in the image.

curl -s -o /dev/null -w "initial-admin setup -> HTTP %{http_code}\n" http://127.0.0.1/api/signup/setup
curl -s -o /dev/null -w "unauthenticated API -> HTTP %{http_code}\n" http://127.0.0.1/api/users
sudo sqlite3 /var/lib/pocket-id/data/pocket-id.db 'SELECT COUNT(*) FROM webauthn_credentials;'

A sign in link works exactly once. Exchange one and then replay it: the first attempt returns 200, the second is rejected.

T=$(sudo pocket-id-admin-link --token-only); curl -s -o /dev/null -w "one-time link  -> HTTP %{http_code}\n" -X POST http://127.0.0.1/api/one-time-access-token/$T; curl -s -o /dev/null -w "same link again -> HTTP %{http_code}\n" -X POST http://127.0.0.1/api/one-time-access-token/$T

Step 6 - Sign in with your one time link

Open your sign in link in a browser. Pocket ID greets you with its passkey prompt; the one time link signs you straight in without a passkey, which is precisely how you bootstrap.

The Pocket ID sign in page inviting you to authenticate with your passkey

Step 7 - Point your domain at the instance and enable HTTPS

Passkeys need a real domain and a secure context, so this step is what turns the instance into a usable identity provider rather than a working demo.

Create a DNS A record for your chosen name, for example id.example.com, pointing at the instance's public IP (or at an Application Load Balancer or CloudFront distribution in front of it). Then tell Pocket ID that name. The helper refuses a bare IP address on purpose, because a passkey could never be registered against one:

sudo pocket-id-set-url https://id.example.com

Then terminate TLS. You can either put an AWS Application Load Balancer or CloudFront with an ACM certificate in front of the instance, or obtain a certificate on the instance itself with certbot, which edits the nginx site in place and reloads it:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d id.example.com --redirect --agree-tos -m you@example.com

Open 443/tcp in the security group, and mint a fresh sign in link now that the URL has changed:

sudo pocket-id-admin-link

Everything from here happens at https://id.example.com.

Step 8 - Register your passkey and set your email

Once signed in, go to My Account and choose Add Passkey, then follow your browser's prompt to use your fingerprint reader, face unlock, phone or hardware key. Once it is registered it becomes your normal way in. Register a second passkey on another device while you are here - it is the difference between losing a laptop and losing an account, though sudo pocket-id-admin-link over SSH remains your backstop either way.

While you are in My Account, change the admin email from the placeholder admin@pocket-id.invalid to your own address, and adjust the username if you would like.

The Pocket ID account page prompting you to add a passkey, with the placeholder admin email ready to change

Step 9 - Add your users and groups

Under Administration then Users, choose Add User to create an account for each person, and use User Groups to organise them. Each user then registers their own passkey the same way you did: you send them a one time link, they sign in and enrol their device. No password is ever set, sent or stored.

The Pocket ID admin Manage Users view listing the per instance admin account with its display name, email, username and role

Step 10 - Register your first OIDC application

Under Administration then OIDC Clients, choose Add OIDC Client. Give it a name and set its callback URL to the redirect URI your application expects, for example https://grafana.example.com/login/generic_oauth. Pocket ID issues a client ID and client secret; copy the secret then, because it is shown once.

The Pocket ID admin Manage OIDC Clients view listing registered applications including Grafana, Nextcloud and Proxmox VE

In the application itself, configure a generic OIDC or OAuth provider with the client ID and secret you just created, and point it at the issuer from Step 4, which is now https://id.example.com. Most applications discover the rest automatically from /.well-known/openid-configuration. Enable PKCE where the application supports it.

Maintenance

The Ubuntu base applies security updates automatically through unattended upgrades. To upgrade Pocket ID itself, replace the binary with a newer release and restart the service:

sudo systemctl stop pocket-id
sudo curl -fsSL -o /usr/local/bin/pocket-id https://github.com/pocket-id/pocket-id/releases/latest/download/pocket-id_linux_amd64
sudo chmod 0755 /usr/local/bin/pocket-id
sudo systemctl start pocket-id

Your identity data lives entirely in /var/lib/pocket-id/data. Back up that directory together with /etc/pocket-id/encryption.key, because the key is what decrypts it. Neither is any use without the other:

sudo tar czf pocket-id-backup.tar.gz /var/lib/pocket-id/data /etc/pocket-id/encryption.key

Pocket ID is licensed under the BSD 2-Clause License. The upstream licence text ships on the image at /usr/share/doc/pocket-id/LICENSE.

Support

cloudimg provides 24/7 support for this image. Contact support@cloudimg.co.uk.