Deployment guide

Pocket ID

Overview

This image runs Pocket ID 2.11.0 on Ubuntu 24.04 LTS. Pocket ID is a simple, self-hosted OpenID Connect provider that authenticates people with passkeys instead of 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.

Pocket ID is a single, self-contained Go binary. It embeds its own web interface and stores everything in an embedded SQLite database, so the whole identity service is one process and one file. It suits setups that need OIDC single sign-on for a handful of self-hosted applications and not a large identity suite.

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. On a fresh public IP that is a real risk, because whoever claims your identity provider owns every application behind it. This image therefore ships with no user, no passkey, no signing key and no secret at all. During first boot, pocket-id-firstboot.service creates the sole admin for your VM specifically, which closes the setup route before the VM 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 VM in a root-only file, or a fresh link that you create over SSH. Your SSH key is the root of trust.

What you get:

  • 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 Azure Load Balancer health probes.
  • A per-VM admin account and one-time sign-in link generated on first boot and recorded at /root/pocket-id-credentials.txt (mode 0600).
  • A per-VM encryption key generated on first boot, so no two VMs 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.
  • An Ubuntu 24.04 LTS base, patched at build time, with unattended security upgrades enabled.
  • 24/7 SecureAnyCloud support.

Prerequisites

  • An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region.
  • A VM size of Standard_B2s (2 vCPU / 4 GiB RAM) is ample, because Pocket ID is a single lightweight Go process.
  • NSG inbound rules that 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. Plan for this 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://<vm-ip>/ in any browser. The VM comes up fully working on its IP address, and you can sign in and configure it there. To register passkeys and run it for real, you need a domain name and a certificate. Step 8 covers that.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Pocket ID by SecureAnyCloud, and select Create. On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

az vm image terms accept --urn sac1647283583153:pocket-id-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-rg \
  --name my-pocket-id \
  --image sac1647283583153:pocket-id-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group my-rg --name my-pocket-id --port 22 --priority 1001
az vm open-port --resource-group my-rg --name my-pocket-id --port 80 --priority 1002

Step 3 - Connect to your VM

ssh azureuser@<vm-ip>

Step 4 - Confirm the services are running

All three units should report active. Pocket ID should listen 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 5 - Retrieve your one-time admin sign-in link

First boot created the sole admin for this VM and created 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 owned by root with mode 0600. It looks like this, with the token masked:

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

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

sudo pocket-id-admin-link

Step 6 - Confirm the provider is serving

The health endpoint answers, and the OIDC discovery document reports the issuer your applications will use and 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 7 - Confirm no credential shipped in the image

Verify this yourself. It is the core security argument for running an identity provider from a prebuilt image.

The initial admin setup route returns 404, which means the admin was already created for this VM and nobody else can claim this instance. The API rejects unauthenticated callers with 401. 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 a link, then replay it. The first attempt returns 200, and 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 8 - Point your domain at the VM and enable HTTPS

Passkeys need a real domain and a secure context, so this step turns the VM into a usable identity provider.

Create a DNS A record for your chosen name, for example id.example.com, that points at the VM's public IP. Then give that name to Pocket ID. 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

Next, obtain a certificate. Certbot 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 NSG, then create a fresh sign-in link now that the URL has changed:

sudo pocket-id-admin-link

From here on, work at https://id.example.com.

Step 9 - Sign in and register your passkey

Open your sign-in link in a browser. Pocket ID shows its passkey prompt.

The one-time link signs you straight in without a passkey, which is how you bootstrap. Go to My Account and choose Add Passkey. Follow your browser's prompt to use your fingerprint reader, face unlock, phone or hardware key. Once registered, the passkey appears in the Passkeys list and becomes your normal way in.

Register a second passkey on another device while you are here. Pocket ID reminds you to. A second passkey is the difference between losing a laptop and losing an account, although sudo pocket-id-admin-link over SSH remains your backstop either way.

While you are in My Account, change the admin email from the temporary address admin@pocket-id.invalid to your own address. You can also change the user name.

Step 10 - 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 registers their own passkey the same way you did. You send them a one-time link, and they sign in and enrol their device. No password is ever set, sent or stored.

Step 11 - 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 a client secret. Copy the secret immediately, because it is shown only once.

In the application itself, configure a generic OIDC or OAuth provider with the client ID and secret you just created. Point it at the issuer from Step 6, 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

All of your identity data lives in /var/lib/pocket-id/data. Back up that directory together with /etc/pocket-id/encryption.key, because the key decrypts the data. Neither is useful 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 is on the image at /usr/share/doc/pocket-id/LICENSE.

Support

SecureAnyCloud provides 24/7 support for this image. Contact sales@secureanycloud.com.

Deploy on Azure

Launch Pocket ID on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure