feat(nixos): add opt-in printing and scanning module
New `modules/printing-scanning.nix` exposes `local.printing.*` and `local.scanning.*` (CUPS drivers, SANE with a Canon BJNP `bjnpHosts` escape hatch, shared Avahi mDNS), all off by default so a consumer opts in and a server gets none of it. Imported from `modules/nixos.nix`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# Printing and scanning, opt-in and off by default. Both are network-facing
|
||||
# (CUPS, and mDNS discovery for WiFi devices), so a consumer that doesn't want
|
||||
# them — a server, a hardened host — simply leaves the flags off and gets none
|
||||
# of it: no avahi, no open firewall, no cups. Nothing to override.
|
||||
#
|
||||
# Printers take vendor drivers (the `drivers` option, never hard-coded).
|
||||
# Scanners are driverless by default via sane-airscan (eSCL/WSD); the one
|
||||
# exception is Canon's BJNP protocol, whose hosts are listed in `bjnpHosts`.
|
||||
# Avahi (mDNS) is shared by both and comes up when either is enabled, so WiFi
|
||||
# devices are discoverable.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.local;
|
||||
netDiscovery = cfg.printing.enable || cfg.scanning.enable;
|
||||
in
|
||||
{
|
||||
options.local = {
|
||||
printing = {
|
||||
enable = lib.mkEnableOption "CUPS printing (WiFi/driverless-friendly)";
|
||||
drivers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [ ];
|
||||
example = lib.literalExpression "[ pkgs.gutenprint ]";
|
||||
description = "Extra CUPS driver packages (vendor/model specific).";
|
||||
};
|
||||
};
|
||||
scanning = {
|
||||
enable =
|
||||
lib.mkEnableOption "SANE scanning with driverless network scanners (sane-airscan)";
|
||||
bjnpHosts = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = lib.literalExpression ''[ "bjnp://192.168.1.50" ]'';
|
||||
description = ''
|
||||
Network scanners reachable over Canon's BJNP protocol, registered
|
||||
with SANE's `pixma` backend (written to `/etc/sane.d/pixma.conf`).
|
||||
BJNP is not driverless eSCL/WSD, so `sane-airscan` can't see these;
|
||||
and BJNP broadcast auto-discovery is usually dropped by the firewall,
|
||||
so list each device's `bjnp://<ip>` explicitly.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.printing.enable {
|
||||
services.printing = {
|
||||
enable = true;
|
||||
drivers = cfg.printing.drivers;
|
||||
};
|
||||
})
|
||||
|
||||
# sane-airscan = driverless eSCL/WSD; hardware.sane also creates the
|
||||
# `scanner` group + udev rules. Group membership is per-user → inventory.
|
||||
# A pixma.conf built the same way the module builds net.conf (a text file
|
||||
# dropped at /etc/sane.d/, merged by mkSaneConfig) registers BJNP hosts.
|
||||
(lib.mkIf cfg.scanning.enable {
|
||||
hardware.sane = {
|
||||
enable = true;
|
||||
extraBackends = [ pkgs.sane-airscan ]
|
||||
++ lib.optional (cfg.scanning.bjnpHosts != [ ]) (pkgs.writeTextFile {
|
||||
name = "sane-pixma-net-conf";
|
||||
destination = "/etc/sane.d/pixma.conf";
|
||||
text = lib.concatMapStrings (h: h + "\n") cfg.scanning.bjnpHosts;
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
# mDNS so CUPS/SANE can discover WiFi printers and scanners on the LAN.
|
||||
(lib.mkIf netDiscovery {
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user