163 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| 
 | |
| with lib;
 | |
| 
 | |
| let
 | |
| 
 | |
|   pkg = if config.hardware.sane.snapshot
 | |
|     then pkgs.sane-backends-git
 | |
|     else pkgs.sane-backends;
 | |
| 
 | |
|   sanedConf = pkgs.writeTextFile {
 | |
|     name = "saned.conf";
 | |
|     destination = "/etc/sane.d/saned.conf";
 | |
|     text = ''
 | |
|       localhost
 | |
|       ${config.services.saned.extraConfig}
 | |
|     '';
 | |
|   };
 | |
| 
 | |
|   netConf = pkgs.writeTextFile {
 | |
|     name = "net.conf";
 | |
|     destination = "/etc/sane.d/net.conf";
 | |
|     text = ''
 | |
|       ${lib.optionalString config.services.saned.enable "localhost"}
 | |
|       ${config.hardware.sane.netConf}
 | |
|     '';
 | |
|   };
 | |
| 
 | |
|   env = {
 | |
|     SANE_CONFIG_DIR = config.hardware.sane.configDir;
 | |
|     LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ];
 | |
|   };
 | |
| 
 | |
|   backends = [ pkg netConf ] ++ 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
 | |
| 
 | |
| {
 | |
| 
 | |
|   ###### interface
 | |
| 
 | |
|   options = {
 | |
| 
 | |
|     hardware.sane.enable = mkOption {
 | |
|       type = types.bool;
 | |
|       default = false;
 | |
|       description = ''
 | |
|         Enable support for SANE scanners.
 | |
| 
 | |
|         <note><para>
 | |
|           Users in the "scanner" group will gain access to the scanner, or the "lp" group if it's also a printer.
 | |
|         </para></note>
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     hardware.sane.snapshot = mkOption {
 | |
|       type = types.bool;
 | |
|       default = false;
 | |
|       description = "Use a development snapshot of SANE scanner drivers.";
 | |
|     };
 | |
| 
 | |
|     hardware.sane.extraBackends = mkOption {
 | |
|       type = types.listOf types.path;
 | |
|       default = [];
 | |
|       description = ''
 | |
|         Packages providing extra SANE backends to enable.
 | |
| 
 | |
|         <note><para>
 | |
|           The example contains the package for HP scanners.
 | |
|         </para></note>
 | |
|       '';
 | |
|       example = literalExample "[ pkgs.hplipWithPlugin ]";
 | |
|     };
 | |
| 
 | |
|     hardware.sane.configDir = mkOption {
 | |
|       type = types.string;
 | |
|       internal = true;
 | |
|       description = "The value of SANE_CONFIG_DIR.";
 | |
|     };
 | |
| 
 | |
|     hardware.sane.netConf = mkOption {
 | |
|       type = types.lines;
 | |
|       default = "";
 | |
|       example = "192.168.0.16";
 | |
|       description = ''
 | |
|         Network hosts that should be probed for remote scanners.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     services.saned.enable = mkOption {
 | |
|       type = types.bool;
 | |
|       default = false;
 | |
|       description = ''
 | |
|         Enable saned network daemon for remote connection to scanners.
 | |
| 
 | |
|         saned would be runned from <literal>scanner</literal> user; to allow
 | |
|         access to hardware that doesn't have <literal>scanner</literal> 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 = mkMerge [
 | |
|     (mkIf enabled {
 | |
|       hardware.sane.configDir = mkDefault "${saneConfig}/etc/sane.d";
 | |
| 
 | |
|       environment.systemPackages = backends;
 | |
|       environment.sessionVariables = env;
 | |
|       services.udev.packages = backends;
 | |
| 
 | |
|       users.groups."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.users."scanner" = {
 | |
|         uid = config.ids.uids.scanner;
 | |
|         group = "scanner";
 | |
|       };
 | |
|     })
 | |
|   ];
 | |
| 
 | |
| }
 | 
