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
80reverse proxying the interface, plus an unauthenticated/healthzendpoint 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(mode0600). - A per-VM encryption key generated on first boot, so no two VMs share one.
pocket-id.service,nginx.serviceand a one-shotpocket-id-firstboot.serviceas systemd units, enabled and active.pocket-id-admin-linkandpocket-id-set-urlhelper 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/tcpfrom your management network and80/tcp(plus443/tcponce you add TLS). Port1411never 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 1002Step 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 nginxsudo 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.txtThe 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-linkStep 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 -1curl -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/setupcurl -s -o /dev/null -w "unauthenticated API -> HTTP %{http_code}\n" http://127.0.0.1/api/userssudo 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/$TStep 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.comNext, 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.comOpen 443/tcp in the NSG, then create a fresh sign-in link now that the URL has changed:
sudo pocket-id-admin-linkFrom 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-idAll 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.keyPocket 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
Overview
This AMI 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 AMI 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 instance specifically, 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 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
80reverse proxying the interface, plus an unauthenticated/healthzendpoint 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(mode0600). - A per-instance encryption key generated on first boot, so no two instances share one.
pocket-id.service,nginx.serviceand a one-shotpocket-id-firstboot.serviceas systemd units, enabled and active.pocket-id-admin-linkandpocket-id-set-urlhelper commands.- A fully patched Ubuntu 24.04 LTS base with unattended security upgrades enabled.
- 24/7 SecureAnyCloud support.
Prerequisites
- An AWS account, an EC2 key pair in the target region, and a VPC with a public subnet.
- An instance type of m5.large (2 vCPU / 8 GiB RAM) is recommended, although Pocket ID is a single lightweight Go process and runs comfortably.
- Security group inbound rules that allow
22/tcpfrom your management network and80/tcp(plus443/tcponce you add TLS). Port1411never 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://<instance-ip>/ in any browser. The instance 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 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:
- Ubuntu 24.04: SSH login user ubuntu
ssh -i /path/to/key.pem ubuntu@<instance-public-ip>Step 1 - Launch from the AWS Marketplace
Find Pocket ID by SecureAnyCloud in the AWS Marketplace. Choose Continue to Subscribe, then Continue to Configuration and Continue to Launch. Pick your region, the m5.large instance type, your VPC subnet and your EC2 key pair. In 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. Pocket ID should listen on 127.0.0.1:1411 only, with nginx on port 80.
systemctl is-active pocket-id pocket-id-firstboot nginxsudo 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 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.txtThe file is owned by root with mode 0600. It looks like this, with the token masked:
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 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-linkStep 4 - 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 -1curl -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
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 instance and nobody else can claim it. 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/setupcurl -s -o /dev/null -w "unauthenticated API -> HTTP %{http_code}\n" http://127.0.0.1/api/userssudo 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/$TStep 6 - Sign in with your one-time link
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.
Step 7 - Point your domain at the instance and enable HTTPS
Passkeys need a real domain and a secure context, so this step turns the instance into a usable identity provider.
Create a DNS A record for your chosen name, for example id.example.com, that points at the instance's public IP (or at an Application Load Balancer or CloudFront distribution in front of it). 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.comNext, terminate TLS. You can put an AWS Application Load Balancer or CloudFront with an ACM certificate in front of the instance. Alternatively, 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.comOpen 443/tcp in the security group, then create a fresh sign-in link now that the URL has changed:
sudo pocket-id-admin-linkFrom here on, work 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. Follow your browser's prompt to use your fingerprint reader, face unlock, phone or hardware key. Once registered, the passkey becomes your normal way in. Register a second passkey on another device while you are here. 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 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 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 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 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 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-idAll 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.keyPocket 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 AWS
Launch Pocket ID Passwordless OIDC Provider with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com