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
'';