Files
printserver/openspec/changes/archive/2026-10-18-add-cups-printserver-container/design.md
T
juergen adaa11e416 Archive the add-cups-printserver-container change
Moves the completed change to openspec/changes/archive/2026-10-18-add-cups-printserver-container/ and syncs the printserver/cups capability into openspec/specs/.
2026-10-18 16:54:54 +02:00

106 lines
5.1 KiB
Markdown

# Design
## Context
See proposal.md. We need a Podman container that runs CUPS for the Brother
HL-4150CDN network printer and shares it over IPP/AirPrint.
Facts established while exploring the device at `192.168.100.7`:
- The printer is a Brother HL-4150CDN (`Ver.1.22`) with PCL6 and **BR-Script3
(PostScript 3)** emulation — `@PJL INFO CONFIG` lists `POSTSCRIPT`.
- Open services: `:9100` (raw/AppSocket), `:515` (LPR/LPD), `:631` (IPP/IPPS)
and `:80` (Brother web UI). It has one paper cassette plus the MP tray.
- A raw PostScript job sent to `:9100` is interpreted by the printer, and a full
CUPS job with `Duplex=DuplexNoTumble BRPrintQuality=Color` printed correctly
(duplex, colour).
An earlier iteration used Brother's Linux packages. That vendor CUPS chain is
broken in `debian:bookworm-slim`: `filterhl4150cdn` needs `file` (and `a2ps` as
a fallback), which are absent, so the filter exits 1 and emits zero bytes. That
chain also rasterises locally (Ghostscript → `ppmraw` → `brhl4150cdnfilter`) and
stores per-queue options in a single global file (`brhl4150cdnrc`), which is
heavy and racy. The packages have since been removed from the repository.
Crucially, the Brother **vendor** PPD (`brhl4150cdn.ppd`) cannot be used for
direct PostScript because its option values are blank (`" "`); all
option handling lives in the vendor filter. Brother's **BR-Script3 PPD**, in
contrast, encodes every option as PostScript `setpagedevice`.
## Goals / Non-Goals
**Goals:**
- Build a working CUPS image for Podman with no 32-bit dependencies.
- Drive the printer with its native PostScript (BR-Script3) interpreter.
- Preserve the hardware options the user cares about: paper tray, duplex and
colour/mono (plus the other options the PPD exposes).
- Share the queue over IPP and advertise it via AirPrint.
- Keep the printer address/name runtime-configurable.
**Non-Goals:**
- Managing multiple printers.
- Sharing via SMB/Samba (Windows uses a client-side Brother driver).
- Persisting CUPS spool/state beyond the container lifecycle.
- TLS for the CUPS web interface.
## Decisions
### Base image and packages
Use `debian:bookworm-slim` with `cups`, `cups-client`, `cups-filters`,
`avahi-daemon`, `avahi-utils`, `libnss-mdns`, `dbus`, `ghostscript` and
`poppler-utils`. No `dpkg --add-architecture i386` and no Brother `.deb`
packages: the job is converted to PostScript in CUPS and interpreted by the
printer, so no vendor binary is needed.
_Alternative considered:_ keep Brother's Linux CUPS wrapper + LPR filter. It
provides the same options but requires 32-bit libraries, Ghostscript
rasterisation and the missing `file`/`a2ps` tools, and it writes options to a
single global config file. Rejected.
### Print path: direct PostScript via the BR-Script3 PPD
Install Brother's official BR-Script3 PPD as
`/usr/share/cups/model/BR4150_2.PPD` (committed at
`assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`, extracted from the vendor Windows
driver) and create the queue with it. CUPS's `pstops` filter reads the PPD and
injects the selected option code (e.g. `/BRFeeder`, `/Duplex`,
`/BRProcessColor`, `/MediaType`) into the job; the PPD's `*JCLBegin`,
`*JCLToPSInterpreter` and `*JCLEnd` entries wrap it in PJL. The result is
forwarded unchanged to the printer.
A stock PostScript PPD (like CUPS's own `generic.ppd`) has no `*cupsFilter`
either, and CUPS accepts such PPDs — the printer's native format is
`application/vnd.cups-postscript`.
### Device URI
Use raw AppSocket as the default: `socket://<ip>:9100`. `lpd://<ip>/binary_p1`
and `ipp://…` remain available through `PRINTER_PROTOCOL`/`PRINTER_URI`.
### Client support
- macOS / iOS / iPadOS: AirPrint → CUPS. The queue advertises `image/urf`,
`image/pwg-raster`, `application/pdf` and `application/postscript`, with
`urf-supported = V1.4,CP1,W8,PQ4,SRGB24,RS600,DM1,FN3`, `sides-supported`
(one-sided/two-sided long/short edge) and `color-supported = true`.
- Linux: IPP / IPP Everywhere, or plain IPP with PDF/PostScript.
- Windows: client-side Brother BR-Script3 Windows driver, pointed at the
printer directly or at the shared queue.
### Runtime configuration
The printer endpoint and advertised name come from environment variables
(`PRINTER_IP`, `PRINTER_PROTOCOL`, `PRINTER_URI`, `PRINTER_NAME`,
`PRINTER_DESCRIPTION`, `PPD_FILE`) rather than being baked into the image. The
entrypoint derives the URI and runs `lpadmin` on startup, then shares the queue.
## Risks / Trade-offs
- [Risk] The AirPrint path (URF → PDF → PostScript) relies on cups-filters'
`rastertopdf`; it was not exercised with a real URF job during exploration.
macOS/iOS printing should be verified end to end.
- [Risk] Colour handling now relies on the printer's PostScript RIP rather than
Brother's host-side colour tables; output may differ slightly from the vendor
raster driver.
- [Risk] The committed PPD is a Windows PPD and contains no CUPS-specific keys.
CUPS accepts it as a PostScript PPD (verified for this CUPS version), but this
should be re-checked on CUPS upgrades.
- [Risk] Avahi needs host networking (or equivalent) to advertise mDNS.
- [Risk] CUPS state is not persisted; the queue is recreated on every start.