printer-agent deployment guide

Turn a Linux host into a shared-printer node on the PrintHub community

printer-agent is a small Rust daemon that runs on the host sitting next to a printer. It holds a long-lived WebSocket to printhub-host, downloads the PDF when a job arrives, and submits it to the printer via IPP.

1. Architecture

Three hops make up the pipeline: the browser (Next.js frontend) → printhub-host (Go backend, auth, job scheduling, file storage) → printer-agent (Rust client) → IPP printer. The agent never opens inbound ports — it is a pure outbound client.

Browser ──HTTP──> printhub-host ──WebSocket──> printer-agent ──IPP──> Printer
                                       │
                                       └──Object storage (PDF jobs)──

2. Prerequisites

Before you start, confirm:

  • Supported distributions: Debian 11 (bullseye) / 12 (bookworm) / 13 (trixie); Ubuntu 20.04 / 22.04 LTS / 23.04+.
  • A printer with IPP enabled (most Wi-Fi-enabled consumer / office printers ship with it), on the same LAN as the agent host.
  • The agent host must be able to reach the printhub-host WebSocket port (443 or 80) and the printer's IPP port (default 631).
  • A registration token issued by the PrintHub backend (see next section).

3. Get a registration token

Registration tokens are issued per user; one token = one printer.

  1. Sign in to PrintHub, then go to "Settings" → "Printers".
  2. On the "My printers" tab click the "Issue token" button.
  3. Confirm the dialog and copy the token (format: phb.<owner_uuid>.<secret>).
  4. ⚠️ The token is shown only once — write it to the agent's config file immediately.

Once the token is in config.toml and the agent connects for the first time, printhub-host auto-creates the printer and stores the token as key_prefix + bcrypt hash. For the full protocol details, see "Auto-registration mechanism" in the printhub-host docs.

4. Install — DEB package (recommended)

The DEB is built by Gitea Actions on every v*.*.* tag push; download it from the project's release page.

Go to https://git.duguying.net/cloudprinter/printer-agent/releases and download the latest printer-agent_<version>_amd64.deb.

Install with dpkg and auto-fix any missing dependencies:

sudo dpkg -i printer-agent_<version>_amd64.deb
sudo apt-get install -f

File layout after install

/usr/local/printer-agent/bin/printer-agent
/usr/local/printer-agent/bin/pdf2printable
/usr/local/printer-agent/conf/config.toml
/usr/bin/printer-agent  (symlink)
/usr/bin/pdf2printable (symlink)

5. Install — Docker

The official image is based on ubuntu:latest with WORKDIR /root/printer-agent. Mount the config directory and run detached:

Prepare the config directory

On the host, create /etc/printer-agent and drop your conf/config.toml in.

Start the container

docker run -d --name printer-agent \
  --restart unless-stopped \
  -v /etc/printer-agent/conf:/root/printer-agent/conf:ro \
  -v /var/log/printer-agent:/root/printer-agent/log \
  git.duguying.net/cloudprinter/printer-agent:latest

6. Install — build from source

For users who need custom patches or unreleased versions.

Build dependencies: Rust 1.70+, g++, libpoppler-glib-dev, libglib2.0-dev, libcairo2-dev, libjpeg-dev, libcurl4-openssl-dev, zlib1g-dev.

make build           # debug build
make pack           # release build, output to dist/
make deb            # rebuild the DEB (compiles ppm2pwg automatically)

Windows users should use the PowerShell script: powershell -ExecutionPolicy Bypass -File .\build.ps1 release

7. Install — Windows

For the graphical Windows installer, use the Windows entry (v1.0.27) inside the "Download printer-agent" dialog under "My Printers". Download printer-agent-setup-1.0.27.exe and double-click to install. This guide focuses on Linux deployment.

8. Configure conf/config.toml

All runtime behaviour is controlled by conf/config.toml. Every field is explained below.

[printer]

[printer]
ipp_addr = "ipp://192.168.1.139:631/ipp/print"   # IPP target; PDFs received from the host are submitted here

[remote]

[remote]
addr = "wss://your-printhub-host.example.com"   # required, must start with ws:// or wss://
# download_addr = "https://your-printhub-host.example.com"   # optional; derived from addr if omitted

[agent]

[agent]
token = "phb.<owner_uuid>.<secret>"   # required, the token from section 3
# pong_timeout = 60        # heartbeat timeout in seconds, default 60
# reconnect_base_ms = 1000 # first reconnect delay in ms, default 1000
# reconnect_max_ms = 30000 # max reconnect delay in ms, default 30000

[log]

[log]
path = "log/printer-agent.log"   # relative to the working directory; consider a dedicated mount
level = "info"                   # trace / debug / info / warn / error
frag_size = 1024                 # fragment size in KB
frag_num = 10                    # number of fragments to retain
frag_gzip = false                # gzip old fragments

9. Run as a daemon

After configuring, start the long-running process with the -d flag. Note: printer-agent has no `daemon` subcommand — use the top-level -d / --daemon flag.

printer-agent -d
# equivalent:
printer-agent --daemon

Use a non-default config path: printer-agent -d --config /etc/printer-agent/config.toml:

Foreground for debugging: printer-agent -d -v # also turns on verbose logs to stderr and the log file:

10. Supervise with systemd

The DEB package does not ship a systemd unit. Save the content below as /etc/systemd/system/printer-agent.service, then enable it:

[Unit]
Description=PrintHub printer-agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=printer-agent
Group=printer-agent
ExecStart=/usr/local/printer-agent/bin/printer-agent -d --config /usr/local/printer-agent/conf/config.toml
Restart=always
RestartSec=5

# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/log/printer-agent /usr/local/printer-agent/log

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now printer-agent
sudo systemctl status printer-agent

11. Verify & troubleshoot

After startup, check in this order:

  • log/printer-agent.log should show "start daemon", "WebSocket connected", and "identify → status=online" lines.
  • On printhub-host, "My printers" should show the device as "Online".
  • Locally run printer-agent --show-printer; it should return IPP attributes, proving the printer is reachable.
  • Submit a test job and watch its status in "Print records" go pending → printing → done.

Common issues

  • 401 immediately on startup: check that the [agent].token in config.toml has no surrounding whitespace and that all three phb.<owner>.<secret> segments are present.
  • Reconnect loop, never registers: the owner may have been deleted, or the token has been revoked. Re-issue under "My printers".
  • Jobs reach the agent but fail at IPP: first run printer-agent --show-printer to verify reachability; check whether UDP/TCP 631 is open.
  • Downloaded job file starts with { or [: the file is broken or the download URL is stale. Re-submit from the UI; the agent logs the first 256 bytes to help diagnosis.
  • Log says "download_url is empty": printhub-host cannot find a token for this printer. Run printhub-host regenerate-printer-token <printer_id> to re-issue.

12. Uninstall & upgrade

  • DEB: sudo dpkg -r printer-agent — also removes the /usr/bin symlinks.
  • Docker: docker rm -f printer-agent; docker image rm for the image if no longer needed.
  • Source: delete the build artifacts (dist/, target/) and the binary.
  • Before upgrading, stop the service (systemctl stop printer-agent or docker stop printer-agent), replace the binary, then start. The config file can usually be reused across minor versions.

13. Protocol reference

Agent and host communicate via a JSON envelope, protocol version 1.0. See sections 8 and 9 of printhub-host's docs/AGENT_REGISTRATION.md for the full frame types, field semantics, and security considerations.