saned + scanservjs + usbip client in a podman container
  • Shell 52.5%
  • Dockerfile 47.5%
Find a file
raf 3eb6d7f432 Initial scannerserver: saned + scanservjs + usbip client container
Debian 13 base, runs saned on :6566 and scanservjs web UI on :8090.
entrypoint optionally attaches a remote USB device via usbip before
starting SANE (USBIP_REMOTE_HOST + USBIP_BUSID env vars).

Files: Containerfile, entrypoint.sh, saned.conf, net.conf,
scannerserver.container quadlet, README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:57:28 +02:00
Containerfile Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00
entrypoint.sh Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00
net.conf Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00
README.md Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00
saned.conf Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00
scannerserver.container Initial scannerserver: saned + scanservjs + usbip client container 2026-04-17 12:57:28 +02:00

scannerserver

Podman container providing:

  • saned (SANE network scanner daemon) on :6566
  • scanservjs web UI on :8080
  • usbip client — attach a USB scanner from a remote Linux host over the network

Use case: a scanner is physically plugged into a remote Linux machine; this container on ps1raf attaches the device via usbip, exposes it through saned, and lets users scan through the scanservjs web UI.

Build

podman build -t scannerserver .

Deploy (quadlet)

cp scannerserver.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start scannerserver

Web UI: http://ps1raf:8090/ (container listens on 8080, published as 8090 on host) SANE net: scanimage -L from any client with net in /etc/sane.d/dll.conf and ps1raf in /etc/sane.d/net.conf.

Attaching a remote USB scanner (usbip)

On the remote host with the scanner plugged in:

sudo modprobe usbip-host
sudo usbipd -D                 # start daemon
usbip list -l                  # find bus-id, e.g. 1-1.2
sudo usbip bind -b 1-1.2       # export

On ps1raf (this container), edit scannerserver.container to uncomment:

AddDevice=/dev/vhci
Environment=USBIP_REMOTE_HOST=<remote>
Environment=USBIP_BUSID=1-1.2

Requires vhci-hcd kernel module loaded on the host (sudo modprobe vhci-hcd).

Files

  • Containerfile — Debian 13 + sane-utils + scanservjs + usbip
  • entrypoint.sh — optional usbip attach, then starts saned + scanservjs
  • saned.conf — CIDR allow-list for saned
  • scannerserver.container — quadlet unit
  • output/ — scan outputs (bind-mounted to /output)
  • scans-config/ — persisted scanservjs config

Testing without a scanner

scanimage -L will list No scanners were identified. Start the container anyway and verify the UI responds: curl -sS http://localhost:8080/ | head.