Some implementation notes:
* cups-pdf, and cups-pdf-to-pdf,
support multiple instances with differing configurations.
This can be accomplished by creating multiple configuration
files with names `cups-pdf-{instance-name}.conf`.
The Nixos module supports this feature by providing
the option `instances` which is an attrset
mapping instance names to instance configurations.
To simplify module usage,
an instance `pdf` is created by default.
* To use a cups-pdf instance, one also needs
a cups queue that connects to the backend.
The module does this automatically by default,
using the `hardware.printers.ensurePrinters`.
It uses one of the ppd files which is
included in the cups-pdf package.
If this isn't desired (e.g. because printer queues
should be created by hand, or configured differently),
the `installPrinter` option can be turned off
(for each instance separately).
* In our configuration, cups calls external programs
using the `cups` account and the `lp` group.
cups-pdf refuses to operate without root privileges,
likely because it needs to change the
ownership of it output pdf files so that
(only) the print job's owner can access them.
The module installs a suid root wrapper for the backend
program that can only be called by the `lp` group.
The cups-pdf package is replaced by a wrapper
package which calls the suid root wrapper.
So cups can call its backend programs as usual.
Silence the systemd warning
ListenStream= references a path below legacy directory /var/run/, updating /var/run/cups/cups.sock → /run/cups/cups.sock; please update the unit file accordingly
by resetting the value coming from the upstream unit.
The directory is already set up by cups.socket: managing it with
RuntimeDirectory in cups.service is unnecesary and has the unwanted
effect that upon stopping cupsd systemd will remove it. This includes
the /run/cups/cups.sock socket, so it breaks socket activation.
This will remove all state directories related to CUPS on startup, which
is particularly useful for guaranteeing that printer discovery works
more reliably on some networks, since CUPS will no longer be able to
store state that effects the next run of the service, such as old
printer names and mDNS information.
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
the conversion procedure is simple:
- find all things that look like options, ie calls to either `mkOption`
or `lib.mkOption` that take an attrset. remember the attrset as the
option
- for all options, find a `description` attribute who's value is not a
call to `mdDoc` or `lib.mdDoc`
- textually convert the entire value of the attribute to MD with a few
simple regexes (the set from mdize-module.sh)
- if the change produced a change in the manual output, discard
- if the change kept the manual unchanged, add some text to the
description to make sure we've actually found an option. if the
manual changes this time, keep the converted description
this procedure converts 80% of nixos options to markdown. around 2000
options remain to be inspected, but most of those fail the "does not
change the manual output check": currently the MD conversion process
does not faithfully convert docbook tags like <code> and <package>, so
any option using such tags will not be converted at all.
A centralized list for these renames is not good because:
- It breaks disabledModules for modules that have a rename defined
- Adding/removing renames for a module means having to find them in the
central file
- Merge conflicts due to multiple people editing the central file
With CUPS v2.3b5, the configuration directive `SetEnv`
moved from `cupsd.conf` to `cups-files.conf`. See also
d47f6aec43 .
We have to follow up as `SetEnv` is now ignored in `cupsd.conf`.
Without this, executables called by cups
can't find other executables they depend on,
like `gs` or `perl`.
Previously we indirectly suggested that the user use
services.printing.extraConf to set this, but this doesn't work with the
default merge ordering. Fix this by making it an independent option.
Fixes#39611.
Use systemd to create the directory for UNIX socket. Also use localhost instead
of 127.0.0.1 as is done in default cupsd.conf so that IPv6 is enabled when
available.
Additional CUPS drivers can be added via "services.printing.drivers" but
Gutenprint was an exception. It was possible to add a Gutenprint
derivation to that list and it would work at first but unlike the other
drivers Gutenprint requires a script to be run after each update or any
attempt to print something would simply fail and an error would show up
in the jobs queue (http://localhost:631/jobs/):
"The PPD version (5.2.11) is not compatible with Gutenprint 5.2.13.
Please run
`/nix/store/7762kpyhfkcgmr3q81v1bbyy0bjhym80-gutenprint-5.2.13/sbin/cups-genppdupdate'
as administrator."
This is due to state in "/var/lib/cups/ppd" and one would need to run
"/nix/store/.../bin/cups-genppdupdate -p /var/lib/cups/ppd" manually.
The alternative was to enable the following option:
"services.printing.gutenprint" but this had two disadvantages:
1) It is an exception that one could be unaware of or that could
potentially cause some confusion.
2) One couldn't use a customized Gutenprint derivation in
"services.printing.drivers" but would instead have to overwrite
"pkgs.gutenprint".
This new approach simply detects a Gutenprint derivation in
"services.printing.gutenprint" by checking if the meta set of a
derivation contains "isGutenprint = true". Therefore no special
exception for Gutenprint would be required and it could easily be
applied to other drivers if they would require such a script to be run.
printer driver and wrapper are often not written with security in mind.
While reviewing https://github.com/NixOS/nixpkgs/pull/25654 I found
a symlink-race vulnerability within the wrapper code, when writing
unique files in /tmp.
I expect this script to be reused in other models as well
as similar vulnerabilities in the code of other vendors. Therefore
I propose to make /tmp of cups.service private so that only processes
with the same privileges are able to access these files.
even if cups rewrites its config file due to config changes made through
its web-based management UI, we need to keep the PATH pointing to
currently-live nix store directories. fixes#20806.
Need to pass `cups.out` to `systemd.packages`, lest we end up with an invalid
generated unit containing only directives set in the service module.
This patch gives us a valid cups.service unit but, vexingly, does not fix the
test failure at NixOS/nixpkgs#14748