PocketCmd Server
This content is for the 1.0.0 version. Switch to the latest version for up-to-date documentation.
PocketCmd Server is a single Go binary, pcmd, that runs on a Linux or macOS machine you control. The app pairs with it over mutual TLS. Once paired, the server runs the metric commands your team approved, evaluates alert rules, stores your encrypted sync records and manages the members and devices of a team.
The server is open source under the MIT license and free to run. Pairing it from the app requires PocketCmd Pro, as do the features that depend on it: server metrics, alerts, sync and teams. Terminal sessions never pass through the server. The app connects to sshd, mosh-server, etserver or a Telnet daemon directly.
What it provides
Section titled “What it provides”| Function | Details |
|---|---|
| Server metrics | Shell commands that a team member proposes and the owner, or someone the owner granted Add monitoring commands, approves, run on a schedule. There are no built-in metrics: a server with no approved commands collects nothing. Samples are stored in SQLite. See Monitoring. |
| Alerts | Threshold rules evaluated on every sample and delivered through PocketCmd’s push relay to the members’ phones and tablets that allow notifications. |
| Sync | Records are encrypted with AES-256-GCM on the device. The server stores the ciphertext and the metadata it needs to route it. See Self-Hosted Sync. |
| Teams | Owner, admin and member roles, invites, per-member permissions, shared vaults and an owner-only audit log. See Teams. |
| Background service | Installs itself as a systemd user service or an OpenRC service on Linux, or a launchd agent on macOS. |
Quick start
Section titled “Quick start”curl -fsSL https://pocketcmd.com/install.sh | sh -s -- --api 1pcmd--api 1 installs the newest server that speaks API version 1, the version the current app uses. The app shows this command, with its own API version, under Teams › Set up a new server.
The first run prints a QR code and the same pocketcmd:// URL as text. In the app, open Teams and choose Set up a new server to scan the code; the desktop apps have no camera scanner and take the URL through Paste URL instead. The first device to pair becomes the team owner. The server then installs itself as a background service and the command exits.
Installation covers platforms, flags, versions and running without a service. QR Code Pairing describes the steps in the app.
How the connection is secured
Section titled “How the connection is secured”| Layer | Implementation |
|---|---|
| Device identity | An ECDSA P-256 key pair generated on the device. Where a secure element is available (Secure Enclave, Android StrongBox or TEE, TPM 2.0 on Windows and Linux) the key is created inside it and cannot be exported. Only the public key reaches the server. |
| Pairing | A one-time token (32 hex characters, valid for 60 seconds) and the server certificate’s SHA-256 fingerprint, both carried in the QR code. The certificate signing request must contain the device’s own public key. |
| Client certificate | Issued by the server with a 30-minute lifetime and renewed by the app. Every mTLS request checks the issuer and the validity window (expiry plus 10 minutes of grace). A device whose certificate has expired recovers through a signed challenge. |
| Session token | A JWT with a 5-minute lifetime, bound to the client certificate’s fingerprint. Its signing key is derived from the server key with HKDF-SHA256 and is separate from the key that issues certificates. |
| Transport | TLS 1.3 minimum. The server certificate is self-signed ECDSA P-256 with a 100-year validity and serves as the server’s pinned identity. |
| Revocation | Every authenticated request re-checks the device registry, so a removed device is refused on its next request. |
| Rate limits | Routes reachable before a session token is issued allow 60 requests per minute per IP address. /api/cert/challenge also allows 10 per minute per public key. After 3 failed pairing attempts from one IP address, pairing refuses that address for the rest of the 60-second window that began with the first failure. |
The server’s SECURITY.md documents the full model, including what an attacker with access to the server’s disk can and cannot read.
Device states
Section titled “Device states”Every paired device is active, left or revoked. Devices that are left or revoked are refused on every route, and their push registrations are deleted.
| Status | How a device gets there | Can the same key pair again? |
|---|---|---|
active |
Paired, or re-joined through an invite. | n/a |
left |
The device unpaired itself, or its user left the team from this device. | Only by redeeming a valid invite. |
revoked |
Someone else removed it: the owner or an admin, the same member from another device, pcmd revoke-device or the removal of its member. When a member leaves the team, their other devices are revoked. |
Never. Reinstalling the app creates a new key, which can join through an invite. |
Removing a device in the app also publishes a signed revocation record that stops your other devices from sharing vault keys with it. pcmd revoke-device cuts the device’s access immediately but cannot sign that record, because the server holds no device key. Use the app to remove a device that had vault access.
Versions and compatibility
Section titled “Versions and compatibility”The server’s major version is its API version: every 1.x.y release speaks API 1.0. The app sends its API version with every request, and a server that speaks another version refuses the request before anything else happens. The app then shows the server as Incompatible server, with the server’s API version, and stops talking to it until one side is updated. Breaking changes to the CLI, the config file or the wire protocol only ship in a new major version.
To install a server that matches your app, use the command the app shows or pass its API version to the installer with --api. See Server Installation.
When a server stops accepting this device (its certificate was replaced, the device was removed or the server’s data was reset), the app marks it Needs re-pair. After a certificate change, scan the code from pcmd rotate-server-cert; a removed device joins again with an invite.
When Pro ends
Section titled “When Pro ends”The server keeps every device registered. The app stops renewing its certificates and stops syncing, and nothing is unpaired or deleted. When Pro is active again, the app recovers its certificate through the challenge path and runs a full sync pass that pushes the edits made in the meantime.
Requirements
Section titled “Requirements”- Linux or macOS on amd64 or arm64. Windows is not supported.
- For the background service: systemd (user unit) or OpenRC on Linux, launchd on macOS. Without one, run
pcmd --foregroundunder your own supervisor. - A regular user account.
pcmdrefuses to run as root or undersudoon systemd and macOS, because the service and its data belong to the user who installs it. - One inbound TCP port reachable from your devices,
8767by default.
Data location
Section titled “Data location”All state lives under ~/.pocketcmd/ (directory mode 0700):
| Path | Contents |
|---|---|
config.json |
Service mode, port, bind address and advertised address (0600). |
state.db |
SQLite database (0600): users, devices, invites, metric requests, monitoring configuration, push registrations, encrypted sync records and the server log read by pcmd logs (about the last 10,000 entries). |
metrics.db |
SQLite time series of metric samples. |
tls/server.crt, tls/server.key |
The server’s identity certificate and key (0600). |
audit.log |
Security events: pairing, revocations, role and permission changes, ownership transfers, device renames, invites, vault grants, metric-command decisions. Written as JSON lines, 0600, rotated at 100 MB with three old files kept. Read it with pcmd audit. |
server.log |
The launchd service’s standard output and errors on macOS. On systemd that output goes to the journal. |
Back the directory up with pcmd backup. A newer server migrates state.db forward when it starts; an older one refuses to open data written by a newer release, so take a backup before upgrading. The server certificate is the identity every device pinned at pairing time: if tls/ is lost, every device has to pair again.