Moves the completed change to openspec/changes/archive/2026-10-18-add-cups-printserver-container/ and syncs the printserver/cups capability into openspec/specs/.
106 lines
5.1 KiB
Markdown
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.
|