Files
nixos/modules/features/printing/default.nix
T

105 lines
3.8 KiB
Nix
Raw Normal View History

2026-08-16 17:53:05 +01:00
{...}: {
# CUPS printing + eSCL scanning for the networked EPSON ET-8550.
#
# Two queues, deliberately:
# EPSON_ET_8550 driverless / IPP Everywhere. The default. PDF is
# passed straight through and the printer's own RIP
# does the work. 51 page sizes, 26 borderless, and the
# only queue that can print CD/DVDs (MediaType Disc).
# EPSON_ET_8550_Photo Epson ESC/P-R. Host rasterises to ESC/P-R at 360dpi.
# 34 sizes, 12 borderless, no disc support - but it is
# the only way to reach Epson's named media/quality
# presets ("Epson Ultra Glossy-Max Quality" etc) that
# IPP Everywhere cannot express. Kept for photo A/B.
#
# Note both PPDs are 360x360 HWResolution - escpr2 is not higher resolution.
#
# Both queues use the mDNS name, not 10.10.20.62, so a DHCP lease change
# doesn't break them. services.avahi.nssmdns4 is what resolves it.
# Port 9100 is closed on this printer, so socket:// is not an option.
#
# cups-browsed is off: it would auto-create a third duplicate queue for the
# same printer. avahi stays on for mDNS resolution and scanner discovery.
flake.nixosModules.printing = {
config,
lib,
pkgs,
...
}: {
programs.system-config-printer.enable = true;
services.avahi = {
enable = true;
nssmdns4 = true;
};
services.printing = {
enable = true;
browsed.enable = false;
drivers = with pkgs; [
epson-escpr2
];
};
hardware.printers = {
ensureDefaultPrinter = "EPSON_ET_8550";
ensurePrinters = [
{
name = "EPSON_ET_8550";
description = "EPSON ET-8550 (driverless)";
location = "Network";
deviceUri = "ipp://EPSONA70973.local:631/ipp/print";
model = "everywhere";
}
{
name = "EPSON_ET_8550_Photo";
description = "EPSON ET-8550 (ESC/P-R photo presets)";
location = "Network";
deviceUri = "ipp://EPSONA70973.local:631/ipp/print";
model = "epson-inkjet-printer-escpr2/Epson-ET-8550_Series-epson-escpr2-en.ppd";
}
];
};
# hardware/printers.nix orders ensure-printers only after cups.service, but
# our deviceUri is an mDNS name and the driverless queue queries the printer
# while it is created. Run the generated script asynchronously so an offline
# printer cannot fail boot or nixos-rebuild, then retry until it is reachable.
systemd.services.ensure-printers = lib.mkIf (config.hardware.printers.ensurePrinters != [] && config.services.printing.enable) {
after = [
"avahi-daemon.service"
"network-online.target"
"nss-lookup.target"
];
wants = [
"avahi-daemon.service"
"network-online.target"
];
serviceConfig = {
Type = lib.mkForce "simple";
Restart = "on-failure";
RestartSec = "1min";
};
};
# eSCL/AirScan. The printer advertises _uscan._tcp with rs=eSCL and
# mopria-certified-scan=1.3, so sane-airscan drives it with no vendor
# backend. No scanner/lp group needed - there's no local udev device.
#
# sane-backends ships its own `escl` backend which also claims eSCL
# devices. Left enabled it double-lists the scanner and, worse, GETs the
# printer's web root and dumps the HTML response onto scanimage's stdout.
# Disabling it leaves sane-airscan as the only eSCL backend, which reports
# a far better device string (airscan:e0:EPSON ET-8550 Series).
hardware.sane = {
enable = true;
extraBackends = [pkgs.sane-airscan];
disabledDefaultBackends = ["escl"];
};
environment.systemPackages = with pkgs; [
simple-scan
];
};
}