Lucas Janin<p><strong>Pocket-ID: Bare Metal Installation on Debian</strong></p><p>After using PocketID for several months with an LXC installation and Proxmox Helper Scripts, I noticed that the service runs as root. I also learned that a VM installation is more secure than an LXC. This article will guide you on installing Pocket-ID as a non-root service on Debian.</p><p></p><p><strong>Presentation</strong></p><p>First, if you’re not familiar with Pocket-ID, it’s a modern and lightweight OIDC client designed for managing authentication for services like Authentic and Aurelia. Its unique feature is that it exclusively supports passkeys. I use it with several self-hosted services, including Proxmox, Proxmox Backup Server, Komodo, Betszel, Karakeep, and, of course, Headscale/Headplane. For more details, the <a href="https://pocket-id.org" rel="nofollow noopener" target="_blank">official website</a> will surely answer many of your questions. If a Docker installation is more suitable for your environment, I invite you to visit <a href="https://www.blackvoid.club/pocket-id-passkey-oidc-provider" rel="nofollow noopener" target="_blank">BlackVoid’s excellent post</a>. It also details the configuration for using Pocket-ID to connect to Synology DSM.</p><p><strong>Preamble </strong></p><p>Since I’m not short on memory on my Proxmox node and I’m very particular about the security of my home lab, I set about installing a VM. This was laborious, as up to version 0.53, there were two services, numerous dependencies, and required compilations. Despite the many obstacles, I succeeded in my mission! Then, a few hours later, without even having time to savour my small victory, version 1.0 was released. This major revision greatly simplifies things, as it’s an executable. Here is the procedure for a streamlined installation as a service with a non-root user in a Proxmox Debian VM. This procedure should be relatively easy to adapt to other types of configurations. There are many other methods for installing Pocket-ID; I invite you to consult the <a href="https://pocket-id.org/docs/setup/installation" rel="nofollow noopener" target="_blank">installation</a> page on the Pocket-ID website.</p><p><strong>Preparing the VM in Proxmox</strong></p><p>If you are in Proxmox, I invite you to install a Debian VM using the Proxmox Helper Scripts. It is also possible to do this with a lighter Alpine, but I have not yet embarked on this adventure. Choose the advanced mode and adjust for your situation, and change the hostname to “pocketid”.</p><pre><code>bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/debian-vm.sh)"</code></pre><p><strong>QEMU</strong></p><p>It’s a good practice to install the QEMU Guest Agent on your VM. You can follow these steps in the Proxmox console of the VM.</p><p>Update your package list:</p><pre><code>sudo apt update && sudo apt upgrade -y</code></pre><p>Install the Proxmox QEMU Guest Agent package:</p><pre><code>sudo apt install qemu-guest-agent -y</code></pre><p>Start and enable the service:</p><pre><code>sudo systemctl start qemu-guest-agentsudo systemctl enable emu-guest-agent</code></pre><p>Verify that the service is running:</p><pre><code>sudo systemctl status qemu-guest-agent</code></pre><p>This will ensure that the Proxmox QEMU Guest Agent is successfully installed and running on your Debian system.</p><p><strong>Installing Pocket-ID<br></strong></p><p>Get Debian ready</p><pre><code>apt update && apt upgrade -y</code></pre><p>Create a dedicated user</p><pre><code>useradd -r -s /bin/false -m -d /opt/pocket-id pocketid</code></pre><p>Install curl needed for the installation</p><pre><code>apt install -y curl</code></pre><p>Downloading and Installing Pocket-ID</p><pre><code>cd /opt/pocket-idARCH="amd64"LATEST_RELEASE_URL=$(curl -s https://api.github.com/repos/pocket-id/pocket-id/releases/latest | grep "browser_download_url.*pocket-id-linux-${ARCH}" | cut -d '"' -f 4)sudo curl -L -o pocket-id "${LATEST_RELEASE_URL}"sudo chmod +x pocket-idsudo chown pocketid:pocketid pocket-id</code></pre><p>Creating directories for Pocket-ID data</p><pre><code>sudo mkdir -p /opt/pocket-id/data/uploads</code></pre><p>Pocket-ID configuration file. To locate visitors’ IP addresses, I invite you to create an API key on the <a href="https://support.maxmind.com/hc/en-us/articles/4407111582235-Generate-a-License-Key" class="" rel="nofollow noopener" target="_blank">Maxmind</a> website.</p><pre><code>sudo nano /opt/pocket-id/.env</code></pre><pre><code>APP_URL=https://id.xxxx.xxPORT=1411# Database: SQLite, file located at /opt/pocket-id/data/db.sqlite# (relative to WorkingDirectory=/opt/pocket-id)DB_CONNECTION_STRING=file:data/db.sqlite?_journal_mode=WAL&_busy_timeout=2500&_txlock=immediate# Optional: Maxmind License Key for IP GeolocationMAXMIND_LICENSE_KEY="YOUR-MAXMIND-LICENSE-KEY"# Optional: Logging level (debug, info, warn, error)LOG_LEVEL=info</code></pre><p>Make sure all Pocket-ID files have the correct user permissions.</p><pre><code>sudo chown pocketid:pocketid /opt/pocket-id/.envsudo chmod 600 /opt/pocket-id/.env</code></pre><p>Setting up the Pocket-ID service</p><pre><code>sudo nano /etc/systemd/system/pocketid.service</code></pre><pre><code>[Unit]Description=Pocket ID Application ServerAfter=network.target[Service]Type=simpleUser=pocketidGroup=pocketidWorkingDirectory=/opt/pocket-idExecStart=/opt/pocket-id/pocket-idEnvironmentFile=/opt/pocket-id/.envRestart=alwaysRestartSec=10NoNewPrivileges=truePrivateTmp=true[Install]WantedBy=multi-user.target</code></pre><pre><code>sudo systemctl daemon-reloadsudo systemctl enable pocketid.servicesudo systemctl start pocketid.servicesudo systemctl status pocketid.service</code></pre><p>If everything goes as planned, you should receive a confirmation.</p><pre><code>● pocketid.service - Pocket ID Application Server Loaded: loaded (/etc/systemd/system/pocketid.service; enabled; preset: enabled) Active: active (running) since Sun 2025-06-01 07:12:57 EDT; 7s ago Main PID: 28699 (pocket-id) Tasks: 8 (limit: 2309) Memory: 8.7M CPU: 65ms CGroup: /system.slice/pocketid.service └─28699 /opt/pocket-id/pocket-idJun 01 07:12:57 pocketid systemd[1]: Started pocketid.service - Pocket ID Application Server.Jun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 Starting job schedulerJun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 Server listening on 0.0.0.0:1411Jun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 GeoLite2 City database is up-to-dateJun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 Job "UpdateGeoLiteDB" run successfullyJun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 Job "SyncLdap" run successfullyJun 01 07:12:57 pocketid pocket-id[28699]: 2025/06/01 07:12:57 Job "SendHeartbeat" run successfully</code></pre><p><strong>Caddy Reverse Proxy</strong></p><p>Here is my Caddyfile with the /robots.txt file in case it is respected (it’s nice to dream).</p><pre><code># Snippet for robots.txt(common_robots_txt) {handle /robots.txt {# Set the Content-Type headerheader Content-Type "text/plain; charset=utf-8"# Respond with the body and status code 200respond `User-agent: *Disallow: /` 200}}# Pocket-IDid.xxxx.xx {import common_robots_txt# Fallback to reverse proxy for other requestsreverse_proxy 192.168.x.yyy:1411 [xxxx:xxxx:xxxx:xxxx::yyyy]:1411}</code></pre><pre><code>systemctl reload caddy.service </code></pre><p>For the first setup of your Pocket-ID instance, I invite you to create your administrator account at<a href="https://id.xxxx.xx/login/setup." rel="nofollow noopener" target="_blank"> <code>https://id.xxxx.xx/login/setup</code>.</a>It is strongly encouraged to have two passkeys since this is the only way to authenticate. I have one in Bitwarden/Vaultwarden and another in iCloud Keychain (via Safari).</p><p><strong>Update</strong></p><p>Since we’re not using Docker, updating can be a bit more complicated. However, it’s nothing insurmountable, especially since version 1.0 is already compiled. Here’s a small update script that allowed me to move from version 1.0 to 1.1.0 without a hitch.</p><pre><code>nano /root/update-pocketid.sh</code></pre><pre><code>#!/bin/bash# update-pocketid.sh# --- Configuration ---INSTALL_DIR="/opt/pocket-id"SERVICE_NAME="pocketid.service"USER="pocketid"GROUP="pocketid"VERSION_FILE="${INSTALL_DIR}/version.txt" ARCHITECTURE="amd64" # Change if needed (e.g., arm64)# --- End Configuration ---echo "Checking for the latest version of PocketID..."LATEST_TAG_JSON=$(curl -s https://api.github.com/repos/pocket-id/pocket-id/releases/latest)LATEST_TAG=$(echo "$LATEST_TAG_JSON" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') # Version without 'v'LATEST_TAG_WITH_V=$(echo "$LATEST_TAG_JSON" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') # Version with 'v'if [ -z "$LATEST_TAG" ]; then echo "Could not retrieve the latest version from GitHub." exit 1fiecho "Latest version available: v${LATEST_TAG}"CURRENT_VERSION="0" # Default to 0 if no version fileif [ -f "$VERSION_FILE" ]; then CURRENT_VERSION=$(cat "$VERSION_FILE")fiecho "Currently installed version: v${CURRENT_VERSION}"if [ "$LATEST_TAG" = "$CURRENT_VERSION" ]; then echo "PocketID is already up to date (v${CURRENT_VERSION})." exit 0fiecho "New version v${LATEST_TAG} available. Updating..."DOWNLOAD_URL=$(echo "$LATEST_TAG_JSON" | grep -E "browser_download_url.*pocket-id-linux-${ARCHITECTURE}" | cut -d '"' -f 4)if [ -z "$DOWNLOAD_URL" ]; then echo "Could not find the download URL for linux-${ARCHITECTURE} and version v${LATEST_TAG}." exit 1fiecho "Stopping service ${SERVICE_NAME}..."sudo systemctl stop "${SERVICE_NAME}"echo "Backing up the old binary..."BACKUP_NAME="pocket-id_backup_v${CURRENT_VERSION}_$(date +%Y%m%d_%H%M%S)"sudo cp "${INSTALL_DIR}/pocket-id" "${INSTALL_DIR}/${BACKUP_NAME}"echo "Old binary backed up to ${INSTALL_DIR}/${BACKUP_NAME}"</code></pre><p>Make the script executable</p><pre><code>sudo chmod +x /root/update-pocketid.sh</code></pre><p>Create an alias</p><pre><code>alias update='/root/update-pocketid.sh'</code></pre><p>Consider updating the system before updating Pocket-ID.</p><pre><code>sudo apt update && sudo apt upgrade -y</code></pre><p>If you are using Proxmox, I encourage you to take a snapshot just before the update and have regular backups (you never know :-).</p><p><strong>Conclusion</strong></p><p>Now, you are ready to step into the future with OIDC and Passkey. You can visit the <a href="https://pocket-id.org/docs/client-examples" rel="nofollow noopener" target="_blank">Client Examples</a> page to easily configure your services with Pocket-ID. I wish you a safe journey into the exciting world of self-hosting!</p><p></p>