1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7{
8 options = {
9 services.ipp-usb = {
10 enable = lib.mkEnableOption "ipp-usb, a daemon to turn an USB printer/scanner supporting IPP everywhere (aka AirPrint, WSD, AirScan) into a locally accessible network printer/scanner";
11 };
12 };
13 config = lib.mkIf config.services.ipp-usb.enable {
14 systemd.services.ipp-usb = {
15 description = "Daemon for IPP over USB printer support";
16 after = [
17 "cups.service"
18 "avahi-daemon.service"
19 ];
20 wants = [ "avahi-daemon.service" ];
21 serviceConfig = {
22 ExecStart = [ "${pkgs.ipp-usb}/bin/ipp-usb" ];
23 Type = "simple";
24 Restart = "on-failure";
25 StateDirectory = "ipp-usb";
26 LogsDirectory = "ipp-usb";
27
28 # hardening.
29 ProtectHome = true;
30 PrivateTmp = true;
31 PrivateUsers = true;
32 ProtectControlGroups = true;
33 MemoryDenyWriteExecute = true;
34 # breaks the daemon, presumably because it messes with DeviceAllow
35 ProtectClock = false;
36 ProtectKernelTunables = true;
37 ProtectKernelLogs = true;
38 ProtectSystem = "strict";
39 RestrictRealtime = true;
40 RestrictSUIDSGID = true;
41 SystemCallArchitectures = "native";
42 PrivateMounts = true;
43 ProtectHostname = true;
44 ProtectKernelModules = true;
45 RemoveIPC = true;
46 RestrictNamespaces = true;
47 AmbientCapabilities = "";
48 CapabilityBoundingSet = "";
49 NoNewPrivileges = true;
50 RestrictAddressFamilies = [
51 "AF_UNIX"
52 "AF_NETLINK"
53 "AF_INET"
54 "AF_INET6"
55 ];
56 ProtectProc = "noaccess";
57 };
58 };
59
60 # starts the systemd service
61 services.udev.packages = [ pkgs.ipp-usb ];
62 services.avahi = {
63 enable = true;
64 publish = {
65 enable = true;
66 userServices = true;
67 };
68 };
69 # enable printing and scanning by default, but not required.
70 services.printing.enable = lib.mkDefault true;
71 hardware.sane.enable = lib.mkDefault true;
72 # so that sane discovers scanners
73 hardware.sane.extraBackends = [ pkgs.sane-airscan ];
74 };
75}