1 { config, lib, pkgs, ... }:
7 pkg = pkgs.sane-backends.override {
8 scanSnapDriversUnfree = config.hardware.sane.drivers.scanSnap.enable;
9 scanSnapDriversPackage = config.hardware.sane.drivers.scanSnap.package;
12 sanedConf = pkgs.writeTextFile {
14 destination = "/etc/sane.d/saned.conf";
17 ${config.services.saned.extraConfig}
21 netConf = pkgs.writeTextFile {
23 destination = "/etc/sane.d/net.conf";
25 ${lib.optionalString config.services.saned.enable "localhost"}
26 ${config.hardware.sane.netConf}
31 SANE_CONFIG_DIR = config.hardware.sane.configDir;
32 LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ];
35 backends = [ pkg netConf ] ++ optional config.services.saned.enable sanedConf ++ config.hardware.sane.extraBackends;
36 saneConfig = pkgs.mkSaneConfig { paths = backends; inherit (config.hardware.sane) disabledDefaultBackends; };
38 enabled = config.hardware.sane.enable || config.services.saned.enable;
48 hardware.sane.enable = mkOption {
51 description = lib.mdDoc ''
52 Enable support for SANE scanners.
55 Users in the "scanner" group will gain access to the scanner, or the "lp" group if it's also a printer.
60 hardware.sane.snapshot = mkOption {
63 description = lib.mdDoc "Use a development snapshot of SANE scanner drivers.";
66 hardware.sane.extraBackends = mkOption {
67 type = types.listOf types.path;
69 description = lib.mdDoc ''
70 Packages providing extra SANE backends to enable.
73 The example contains the package for HP scanners, and the package for
74 Apple AirScan and Microsoft WSD support (supports many
78 example = literalExpression "[ pkgs.hplipWithPlugin pkgs.sane-airscan ]";
81 hardware.sane.disabledDefaultBackends = mkOption {
82 type = types.listOf types.str;
85 description = lib.mdDoc ''
86 Names of backends which are enabled by default but should be disabled.
87 See `$SANE_CONFIG_DIR/dll.conf` for the list of possible names.
91 hardware.sane.configDir = mkOption {
94 description = lib.mdDoc "The value of SANE_CONFIG_DIR.";
97 hardware.sane.netConf = mkOption {
100 example = "192.168.0.16";
101 description = lib.mdDoc ''
102 Network hosts that should be probed for remote scanners.
106 hardware.sane.drivers.scanSnap.enable = mkOption {
110 description = lib.mdDoc ''
111 Whether to enable drivers for the Fujitsu ScanSnap scanners.
113 The driver files are unfree and extracted from the Windows driver image.
117 hardware.sane.drivers.scanSnap.package = mkOption {
118 type = types.package;
119 default = pkgs.sane-drivers.epjitsu;
120 defaultText = literalExpression "pkgs.sane-drivers.epjitsu";
121 description = lib.mdDoc ''
122 Epjitsu driver package to use. Useful if you want to extract the driver files yourself.
124 The process is described in the `/etc/sane.d/epjitsu.conf` file in
125 the `sane-backends` package.
129 services.saned.enable = mkOption {
132 description = lib.mdDoc ''
133 Enable saned network daemon for remote connection to scanners.
135 saned would be runned from `scanner` user; to allow
136 access to hardware that doesn't have `scanner` group
137 you should add needed groups to this user.
141 services.saned.extraConfig = mkOption {
144 example = "192.168.0.0/24";
145 description = lib.mdDoc ''
146 Extra saned configuration lines.
153 ###### implementation
157 hardware.sane.configDir = mkDefault "${saneConfig}/etc/sane.d";
159 environment.systemPackages = backends;
160 environment.sessionVariables = env;
161 services.udev.packages = backends;
163 users.groups.scanner.gid = config.ids.gids.scanner;
166 (mkIf config.services.saned.enable {
167 networking.firewall.connectionTrackingModules = [ "sane" ];
169 systemd.services."saned@" = {
170 description = "Scanner Service";
171 environment = mapAttrs (name: val: toString val) env;
175 ExecStart = "${pkg}/bin/saned";
179 systemd.sockets.saned = {
180 description = "saned incoming socket";
181 wantedBy = [ "sockets.target" ];
182 listenStreams = [ "0.0.0.0:6566" "[::]:6566" ];
184 # saned needs to distinguish between IPv4 and IPv6 to open matching data sockets.
185 BindIPv6Only = "ipv6-only";
191 users.users.scanner = {
192 uid = config.ids.uids.scanner;
194 extraGroups = [ "lp" ] ++ optionals config.services.avahi.enable [ "avahi" ];