diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 80a9a520e24e..79f1e2097388 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -84,7 +84,7 @@ spamd = 56; #networkmanager = 57; # unused nslcd = 58; - #scanner = 59; # unused + scanner = 59; nginx = 60; chrony = 61; #systemd-journal = 62; # unused diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix index a34037403123..e69209c560b5 100644 --- a/nixos/modules/services/hardware/sane.nix +++ b/nixos/modules/services/hardware/sane.nix @@ -7,9 +7,26 @@ let pkg = if config.hardware.sane.snapshot then pkgs.sane-backends-git else pkgs.sane-backends; - backends = [ pkg ] ++ config.hardware.sane.extraBackends; + + sanedConf = pkgs.writeTextFile { + name = "saned.conf"; + destination = "/etc/sane.d/saned.conf"; + text = '' + localhost + ${config.services.saned.extraConfig} + ''; + }; + + env = { + SANE_CONFIG_DIR = config.hardware.sane.configDir; + LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ]; + }; + + backends = [ pkg ] ++ optional config.services.saned.enable sanedConf ++ config.hardware.sane.extraBackends; saneConfig = pkgs.mkSaneConfig { paths = backends; }; + enabled = config.hardware.sane.enable || config.services.saned.enable; + in { @@ -51,27 +68,77 @@ in hardware.sane.configDir = mkOption { type = types.string; + internal = true; description = "The value of SANE_CONFIG_DIR."; }; + services.saned.enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable saned network daemon for remote connection to scanners. + + saned would be runned from scanner user; to allow + access to hardware that doesn't have scanner group + you should add needed groups to this user. + ''; + }; + + services.saned.extraConfig = mkOption { + type = types.lines; + default = ""; + example = "192.168.0.0/24"; + description = '' + Extra saned configuration lines. + ''; + }; + }; ###### implementation - config = mkIf config.hardware.sane.enable { + config = mkMerge [ + (mkIf enabled { + hardware.sane.configDir = mkDefault "${saneConfig}/etc/sane.d"; - hardware.sane.configDir = mkDefault "${saneConfig}/etc/sane.d"; + environment.systemPackages = backends; + environment.sessionVariables = env; + services.udev.packages = backends; - environment.systemPackages = backends; - environment.sessionVariables = { - SANE_CONFIG_DIR = config.hardware.sane.configDir; - LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ]; - }; - services.udev.packages = backends; + users.extraGroups."scanner".gid = config.ids.gids.scanner; + }) - users.extraGroups."scanner".gid = config.ids.gids.scanner; + (mkIf config.services.saned.enable { + networking.firewall.connectionTrackingModules = [ "sane" ]; - }; + systemd.services."saned@" = { + description = "Scanner Service"; + environment = mapAttrs (name: val: toString val) env; + serviceConfig = { + User = "scanner"; + Group = "scanner"; + ExecStart = "${pkg}/bin/saned"; + }; + }; + + systemd.sockets.saned = { + description = "saned incoming socket"; + wantedBy = [ "sockets.target" ]; + listenStreams = [ "0.0.0.0:6566" "[::]:6566" ]; + socketConfig = { + # saned needs to distinguish between IPv4 and IPv6 to open matching data sockets. + BindIPv6Only = "ipv6-only"; + Accept = true; + MaxConnections = 1; + }; + }; + + users.extraUsers."scanner" = { + uid = config.ids.uids.scanner; + group = "scanner"; + }; + }) + ]; } diff --git a/pkgs/applications/graphics/sane/config.nix b/pkgs/applications/graphics/sane/config.nix index 4b8c7a4fe921..fb4e56eb6cea 100644 --- a/pkgs/applications/graphics/sane/config.nix +++ b/pkgs/applications/graphics/sane/config.nix @@ -4,25 +4,26 @@ with stdenv.lib; let installSanePath = path: '' - if test -e "${path}/lib/sane"; then + if [ -e "${path}/lib/sane" ]; then find "${path}/lib/sane" -maxdepth 1 -not -type d | while read backend; do - ln -s $backend $out/lib/sane/$(basename $backend) + ln -s "$backend" "$out/lib/sane/$(basename "$backend")" done fi - if test -e "${path}/etc/sane.d"; then + if [ -e "${path}/etc/sane.d" ]; then find "${path}/etc/sane.d" -maxdepth 1 -not -type d | while read conf; do - if test $(basename $conf) = "dll.conf"; then - cat $conf >> $out/etc/sane.d/dll.conf + name="$(basename $conf)" + if [ "$name" = "dll.conf" ] || [ "$name" = "saned.conf" ]; then + cat "$conf" >> "$out/etc/sane.d/$name" else - ln -s $conf $out/etc/sane.d/$(basename $conf) + ln -s "$conf" "$out/etc/sane.d/$name" fi done fi - if test -e "${path}/etc/sane.d/dll.d"; then + if [ -e "${path}/etc/sane.d/dll.d" ]; then find "${path}/etc/sane.d/dll.d" -maxdepth 1 -not -type d | while read conf; do - ln -s $conf $out/etc/sane.d/dll.d/$(basename $conf) + ln -s "$conf" "$out/etc/sane.d/dll.d/$(basename $conf)" done fi '';