PrintHook Agent

The service that sits next to the printer.

One static binary per platform, installed as a system service so printers keep working when nobody is logged in, plus a small tray helper for status and settings. It opens outbound HTTPS only, keeps a durable job journal on disk, and updates itself.

Downloads are published per platform in the console under Setup, with SHA-256 checksums.

unattended enrollment, any platform
printhook-agent enroll \
  --server https://api.printhook.io \
  --client-key ck-… \
  --data-dir /var/lib/printhook
# the computer appears in the console within seconds
printhook-agent selftest    # capability dump of every queue and scale
printhook-agent diag        # DNS, TLS, proxy, WebSocket, storage, spooler
printhook-agent update --check

Requirements

Supported platforms

PlatformMinimumPackageNotes
WindowsWindows 10 1809 / Server 2019, x64 or arm64MSI, Authenticode signedPrinters must be installed for the machine (visible to the SYSTEM account); the print spooler service must run. The settings window uses the WebView2 Runtime and falls back to the browser without it.
macOS12 Monterey, Intel or Apple siliconUniversal .pkg, Developer ID signed and notarizedPrinters configured in System Settings (CUPS). The helper is a menu bar app with no Dock tile.
Linuxsystemd, CUPS 2.x, cups-client.deb (Debian, Ubuntu, Raspberry Pi OS 64-bit), .rpm (Fedora, RHEL, Rocky, Alma, openSUSE), amd64 and arm64Runs as the printhook system user; a udev rule grants access to supported USB scales.
DockerDocker 20.10+ / compose v2ghcr.io/printhook/printhook-agent, linux/amd64 and linux/arm64No CUPS server inside; bind-mount the host's CUPS socket or point CUPS_SERVER at a network CUPS server.

Outbound HTTPS on port 443 to the PrintHook hosts is the only network requirement.

Windows (MSI)

The MSI is per machine and needs administrator rights. Interactive: double-click, accept, finish; the tray helper starts at the end and again at every logon. Silent, with unattended enrollment:

msiexec /i PrintHook-1.4.0-x64.msi /qn /norestart ^
  SERVER=https://api.printhook.io CLIENTKEY=ck-... ^
  /l*v %TEMP%\printhook-install.log

SERVER and CLIENTKEY enroll before the service starts; the key never appears in the log. TRAY=0 skips the per-user tray auto-start, INSTALLFOLDER changes the location, and WIPEDATA=1 on uninstall also deletes %PROGRAMDATA%\PrintHook. The service is PrintHookAgent.

macOS (.pkg)

The package is universal (Intel and Apple silicon), Developer ID signed with the hardened runtime and notarized, so Gatekeeper opens it without warnings. Double-click, or:

sudo PRINTHOOK_SERVER=https://api.printhook.io PRINTHOOK_CLIENT_KEY=ck-... \
  installer -pkg PrintHook-1.4.0.pkg -target /

The package installs the LaunchDaemon io.printhook.agent (RunAtLoad, KeepAlive) and the menu bar app /Applications/PrintHook.app. For MDM (Jamf, Kandji, Mosyle), deploy the .pkg as a package policy and pass the two variables through a pre-install script, or run enroll from a post-install script. Uninstall with sudo /Library/PrintHook/uninstall.sh (add --wipe-data to remove the data directory).

Linux (.deb / .rpm)

sudo apt install ./printhook-agent_1.4.0_linux_amd64.deb      # Debian, Ubuntu, Raspberry Pi OS 64-bit
sudo dnf install ./printhook-agent_1.4.0_linux_amd64.rpm      # Fedora, RHEL, Rocky, Alma
sudo zypper install ./printhook-agent_1.4.0_linux_amd64.rpm   # openSUSE

The package creates the printhook system user, installs the unit printhook-agent.service (Restart=always) and enables it at once. Put PRINTHOOK_SERVER and PRINTHOOK_CLIENT_KEY in /etc/printhook/agent.env and the service enrolls itself on first start, or export them for the package-manager run, or enroll afterwards:

sudo printhook-agent enroll --server https://api.printhook.io --client-key ck-... --data-dir /var/lib/printhook
sudo chown -R printhook:printhook /var/lib/printhook/config
sudo systemctl restart printhook-agent

For a remote CUPS server set CUPS_SERVER=host:631 in agent.env. apt remove keeps the data directory; apt purge removes it and the user.

Docker

The image runs the agent with the CUPS backend and contains no CUPS server of its own. Printers must exist on the CUPS server it reaches; network label printers are added there with lpadmin.

docker run -d --name printhook-agent --restart unless-stopped \
  -e PRINTHOOK_SERVER=https://api.printhook.io -e PRINTHOOK_CLIENT_KEY=ck-... \
  -v printhook-data:/var/lib/printhook \
  -v /run/cups/cups.sock:/run/cups/cups.sock \
  ghcr.io/printhook/printhook-agent:1.4.0

Enrollment

Enrollment ties a computer to an account with an agent-scoped computer key (ck- followed by 44 characters). Whichever path you use, the result is the same config.json.

  1. Sign in from the tray helper. Enter the console email and password once. The agent exchanges them for a computer key bound to this computer's install_uuid and stores only the key; the password is never written to configuration, state, logs or diagnostics. Accounts with two-step verification are asked for a code. The account owner receives a "new computer signed in" notice naming the machine.
  2. Paste a computer key created in the console under Computers > Add computer.
  3. Unattended: pass the server URL and key to the installer, or run printhook-agent enroll --client-key as an administrator. This path needs no network at enrollment time; the service validates the key when it first connects.

Claiming a station. Add --station <code> to a sign-in enrollment: the six-character pairing code minted from the station in the console (fifteen minutes, single use), or the station's printed barcode (PHS-…, stable for the life of the station). The computer becomes that bench, and a re-imaged PC re-pairs by scanning the same laminated barcode. A wrong, used or expired code is refused after the password is accepted, so the message tells you which one to fix.

Re-running enroll replaces the key but keeps the install_uuid, so the computer keeps its id in the console. When cloning machine images, enroll after cloning or delete config/install_uuid before capturing, otherwise every clone claims the same computer.

Network and proxies

The agent only makes outbound connections; nothing needs to be opened inbound. Its local control API listens on 127.0.0.1:8895, token-authenticated, for the tray helper.

DestinationPortPurpose
api.printhook.io443Agent gateway (HTTPS and WebSocket, subprotocol printhook.v1), REST fallback, sign-in, release manifests
PrintHook content storage hosts443Presigned downloads of job content above the 64 KB inline limit; uploads of diagnostics bundles
printhook.io443Agent update downloads
Your own content.url hostsas givenOnly when your API calls submit URL jobs; the agent fetches them directly, with Basic or Digest auth if supplied

Proxies: the agent honors HTTPS_PROXY, HTTP_PROXY and NO_PROXY from the environment, or an explicit proxy URL in its configuration. printhook-agent diag tests DNS, TLS, proxy (with 407 detection), the WebSocket upgrade, storage reachability and the spooler, and --export writes a diagnostics zip. Review and redact it before sharing, then email support for transfer guidance. Use the local diagnostics result to investigate connection failures.

Reliability

  • Durable job journal. A job is recorded in a local SQLite ledger, with its content already on disk, before it is acknowledged; marked spooling immediately before the OS is asked to print; and closed with a terminal state. That turns the server's at-least-once delivery into exactly-once printing across restarts and offline gaps.
  • Outbox for state. A terminal state written while offline is reported when the connection returns.
  • Service manager supervision. Restart=always on Linux, KeepAlive on macOS, the Windows service recovery settings on Windows.
  • Session takeover handled. If a second agent claims the same install, the server keeps one session and closes the other with a distinct close code, and the console records a computer.superseded event.

Updates

Once enrolled, the service checks GET /v1/agent-releases/latest hourly. A newer release is downloaded, its SHA-256 and ed25519 manifest signature verified, the in-flight job finished, the executable swapped, and the service restarted by its service manager. Platform signatures (Authenticode, notarization) are checked by the OS when installers run. PRINTHOOK_AUTO_UPDATE=0 disables the hourly check; printhook-agent update --check exits 10 when a newer release exists, and update --rollback restores the previous version.

Data directories

PlatformData directory
WindowsC:\ProgramData\PrintHook
macOS/Library/Application Support/PrintHook
Linux/var/lib/printhook (environment in /etc/printhook/agent.env)
Docker/var/lib/printhook (volume)

config/ holds config.json and install_uuid, readable by administrators and the service only. state/ holds the ledger, the spool of content until it is printed, and state/logs/agent.log (JSON lines, rolled at 5 MB, ten files kept). The computer key appears in logs and diagnostics with only its prefix visible.

Install it, send a test page, call the API.