implement warn on dnssd name collisions

This commit is contained in:
juergen committed 2026-10-20 11:11:45 +02:00
1 parent 3910ab974c
commit f15ea07f44
3 files changed
+159 -16

No files matched your search

+67 -5
View File
@@ -82,7 +82,7 @@ podman run -d --name printserver \
| `PRINTER_IP` | *(empty)* | IP address / host name of the network printer. A device URI is derived from it (see `PRINTER_PROTOCOL`). |
| `PRINTER_URI` | *(empty)* | Full device URI. Overrides `PRINTER_IP` when set. |
| `PRINTER_PROTOCOL` | `socket` | Protocol used with `PRINTER_IP`: `socket`, `lpd` or `ipp`. |
| `PRINTER_NAME` | `HL4150CDN` | CUPS queue name. Also used as the name advertised via AirPrint/DNS-SD. |
| `PRINTER_NAME` | `HL4150CDN` | CUPS queue name. Also the base of the advertised AirPrint/DNS-SD name (`<name> @ <host>`) — while no Description is set; `PRINTER_DESCRIPTION` overrides the advertised name. |
| `PRINTER_DESCRIPTION` | *(empty)* | CUPS printer description (`lpadmin -D`), shown in the CUPS web UI. |
| `PPD_FILE` | `/usr/share/cups/model/BR4150_2.PPD` | PPD used for the queue. |
| `PRINTER_OPTIONS` | *(empty)* | Space-separated PPD option assignments (`key=value`) applied as queue defaults on every start, e.g. `BRColorMode=Vivid TonerSaveMode=False`. Discover the names with `lpoptions -p <queue> -l`. |
@@ -130,14 +130,21 @@ Or specify the URI explicitly for full control:
### Advertised name
`PRINTER_NAME` is used as the CUPS queue name and as the name clients see in
AirPrint discovery. To show a descriptive label in the CUPS web interface,
set `PRINTER_DESCRIPTION` (this does not change the advertised name):
`PRINTER_NAME` is the CUPS queue name. It is also the base of the name clients
see in AirPrint discovery — CUPS advertises `"<name> @ <host>"` — but only as
long as no Description is set: `PRINTER_DESCRIPTION` (the `lpadmin -D`
Description) has precedence and becomes the advertised name instead:
```sh
-e PRINTER_NAME=HL4150CDN -e PRINTER_DESCRIPTION="Brother HL-4150CDN (Office)"
```
advertises the DNS-SD instance `Brother HL-4150CDN (Office) @ <host>`, not
`HL4150CDN @ <host>`. That instance name is what clients pin into their
`dnssd://` device URI, so every queue needs a **unique** Description: two
queues deriving the same name collide, and only one of them is ever advertised
(see *macOS shows the printer offline after some time* under Troubleshooting).
### TLS certificate for `_ipps`
CUPS advertises the queue twice over mDNS: `_ipp._tcp` (plain) and `_ipps._tcp`
@@ -433,7 +440,7 @@ podman cp printserver:/etc/cups/ssl/server.crt . &&
```
A way around either cause is to add the queue from the command line, driverless
over the same secure service (`ipptool -tv ipp://<host>:631/printers/<queue>`
over the same secure service (`ipptool -tv ipp://<host>:631/printers/<queue> <file-to-print>`
prints the UUID; drop the `urn:uuid:` prefix):
```sh
@@ -482,6 +489,61 @@ greyscale. Forcing Ghostscript with `-o pdftops-renderer=gs` would, but that
path is not recommended for Brother printers (bugs in their PostScript
interpreters).
### macOS shows the printer offline after some time
Symptom: the printer was added and printed fine, then macOS reports it
*offline* ("printer is not responding") some hours later — typically after the
container was restarted or after queues were edited on the server. Restarting
the container does not help; removing the printer on the Mac and adding it
again fixes it — until it happens again.
Cause: when macOS adds a Bonjour printer it pins the exact DNS-SD **instance
name** into the queue's device URI:
```text
dnssd://Laserdrucker%20HL-4150CDN%20%40%20podp._ipps._tcp.local./?uuid=…
└── "<Description> @ <host>" — must still resolve hours later
```
CUPS derives that name from the **Description**, not from the CUPS queue name
(the queue name is only the base while no Description is set). Two queues with
the same Description therefore derive the same instance name. Avahi can
register only one service per name, and CUPS 2.4 does not rename on collision
(upstream `scheduler/dnssd.c` still carries a `TODO` for it), so the losing
queue stays *Shared* but is never advertised. The Mac keeps resolving the name
that no longer exists and flips the queue to offline. The lost race is
deterministic — the same queue wins after every restart — which is why
restarting the container never helps, while remove/re-add re-pins the Mac to
the instance that is actually advertised.
The entrypoint logs a warning at startup when it finds such a collision. To
check by hand:
```sh
podman logs printserver 2>&1 | grep 'DNS-SD name' # entrypoint warning, if any
lpstat -v | grep dnssd # the instance name the Mac pinned
podman exec printserver lpstat -l -p # duplicate Descriptions?
dns-sd -B _ipp._tcp # one instance per name?
podman exec printserver avahi-browse -rt _ipps._tcp # what is really advertised
ipptool -tv ipp://<host>:631/printers/<queue> \
/usr/share/cups/ipptool/get-printer-attributes.test # server side itself
```
Two queues showing the same `Description:` while `dns-sd -B` lists only one
instance is the collision. Fix it on the server: give each queue a unique
Description, or remove the redundant queue:
```sh
lpadmin -h <host>:631 -p laserdrucker-im-buero -D "Laserdrucker Buero"
# or drop the duplicate entirely:
lpadmin -h <host>:631 -x laserdrucker-im-buero
```
Then remove the printer on the Mac and add it again — macOS re-pins the device
URI to the instance that is advertised now. The same remove/re-add is needed
after **every** Description change: the pinned name changes with it, and a
container restart alone cannot bring the old name back.
## CUPS 3 and the future of PPDs
Adding the queue with a PPD makes `lpadmin` print: