at 21.11-pre 4.5 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 pkg = pkgs.sane-backends; 8 9 sanedConf = pkgs.writeTextFile { 10 name = "saned.conf"; 11 destination = "/etc/sane.d/saned.conf"; 12 text = '' 13 localhost 14 ${config.services.saned.extraConfig} 15 ''; 16 }; 17 18 netConf = pkgs.writeTextFile { 19 name = "net.conf"; 20 destination = "/etc/sane.d/net.conf"; 21 text = '' 22 ${lib.optionalString config.services.saned.enable "localhost"} 23 ${config.hardware.sane.netConf} 24 ''; 25 }; 26 27 env = { 28 SANE_CONFIG_DIR = config.hardware.sane.configDir; 29 LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ]; 30 }; 31 32 backends = [ pkg netConf ] ++ optional config.services.saned.enable sanedConf ++ config.hardware.sane.extraBackends; 33 saneConfig = pkgs.mkSaneConfig { paths = backends; inherit (config.hardware.sane) disabledDefaultBackends; }; 34 35 enabled = config.hardware.sane.enable || config.services.saned.enable; 36 37in 38 39{ 40 41 ###### interface 42 43 options = { 44 45 hardware.sane.enable = mkOption { 46 type = types.bool; 47 default = false; 48 description = '' 49 Enable support for SANE scanners. 50 51 <note><para> 52 Users in the "scanner" group will gain access to the scanner, or the "lp" group if it's also a printer. 53 </para></note> 54 ''; 55 }; 56 57 hardware.sane.snapshot = mkOption { 58 type = types.bool; 59 default = false; 60 description = "Use a development snapshot of SANE scanner drivers."; 61 }; 62 63 hardware.sane.extraBackends = mkOption { 64 type = types.listOf types.path; 65 default = []; 66 description = '' 67 Packages providing extra SANE backends to enable. 68 69 <note><para> 70 The example contains the package for HP scanners. 71 </para></note> 72 ''; 73 example = literalExample "[ pkgs.hplipWithPlugin ]"; 74 }; 75 76 hardware.sane.disabledDefaultBackends = mkOption { 77 type = types.listOf types.str; 78 default = []; 79 example = [ "v4l" ]; 80 description = '' 81 Names of backends which are enabled by default but should be disabled. 82 See <literal>$SANE_CONFIG_DIR/dll.conf</literal> for the list of possible names. 83 ''; 84 }; 85 86 hardware.sane.configDir = mkOption { 87 type = types.str; 88 internal = true; 89 description = "The value of SANE_CONFIG_DIR."; 90 }; 91 92 hardware.sane.netConf = mkOption { 93 type = types.lines; 94 default = ""; 95 example = "192.168.0.16"; 96 description = '' 97 Network hosts that should be probed for remote scanners. 98 ''; 99 }; 100 101 services.saned.enable = mkOption { 102 type = types.bool; 103 default = false; 104 description = '' 105 Enable saned network daemon for remote connection to scanners. 106 107 saned would be runned from <literal>scanner</literal> user; to allow 108 access to hardware that doesn't have <literal>scanner</literal> group 109 you should add needed groups to this user. 110 ''; 111 }; 112 113 services.saned.extraConfig = mkOption { 114 type = types.lines; 115 default = ""; 116 example = "192.168.0.0/24"; 117 description = '' 118 Extra saned configuration lines. 119 ''; 120 }; 121 122 }; 123 124 125 ###### implementation 126 127 config = mkMerge [ 128 (mkIf enabled { 129 hardware.sane.configDir = mkDefault "${saneConfig}/etc/sane.d"; 130 131 environment.systemPackages = backends; 132 environment.sessionVariables = env; 133 services.udev.packages = backends; 134 135 users.groups.scanner.gid = config.ids.gids.scanner; 136 }) 137 138 (mkIf config.services.saned.enable { 139 networking.firewall.connectionTrackingModules = [ "sane" ]; 140 141 systemd.services."saned@" = { 142 description = "Scanner Service"; 143 environment = mapAttrs (name: val: toString val) env; 144 serviceConfig = { 145 User = "scanner"; 146 Group = "scanner"; 147 ExecStart = "${pkg}/bin/saned"; 148 }; 149 }; 150 151 systemd.sockets.saned = { 152 description = "saned incoming socket"; 153 wantedBy = [ "sockets.target" ]; 154 listenStreams = [ "0.0.0.0:6566" "[::]:6566" ]; 155 socketConfig = { 156 # saned needs to distinguish between IPv4 and IPv6 to open matching data sockets. 157 BindIPv6Only = "ipv6-only"; 158 Accept = true; 159 MaxConnections = 64; 160 }; 161 }; 162 163 users.users.scanner = { 164 uid = config.ids.uids.scanner; 165 group = "scanner"; 166 extraGroups = [ "lp" ] ++ optionals config.services.avahi.enable [ "avahi" ]; 167 }; 168 }) 169 ]; 170 171}