1{
2 config,
3 pkgs,
4 lib,
5 utils,
6 ...
7}:
8
9let
10 cfg = config.services.atalkd;
11
12 # Generate atalkd.conf only if configFile isn't manually specified
13 atalkdConfFile = pkgs.writeText "atalkd.conf" (
14 lib.concatStringsSep "\n" (
15 lib.mapAttrsToList (
16 iface: ifaceCfg: iface + (if ifaceCfg.config != null then " ${ifaceCfg.config}" else "")
17 ) cfg.interfaces
18 )
19 );
20in
21{
22 options.services.atalkd = {
23 enable = lib.mkEnableOption "the AppleTalk daemon";
24
25 configFile = lib.mkOption {
26 type = lib.types.nullOr lib.types.path;
27 default = atalkdConfFile;
28 defaultText = "/nix/store/xxx-atalkd.conf";
29 description = ''
30 Optional path to a custom `atalkd.conf` file. When set, this overrides the generated
31 configuration from `services.atalkd.interfaces`.
32 '';
33 };
34
35 interfaces = lib.mkOption {
36 description = "Per-interface configuration for atalkd.";
37 type = lib.types.attrsOf (
38 lib.types.submodule {
39 options.config = lib.mkOption {
40 type = lib.types.nullOr lib.types.str;
41 default = null;
42 description = "Optional configuration string for this interface.";
43 };
44 }
45 );
46 default = { };
47 };
48 };
49
50 config =
51 let
52 interfaces = map (iface: "sys-subsystem-net-devices-${utils.escapeSystemdPath iface}.device") (
53 builtins.attrNames cfg.interfaces
54 );
55 in
56 lib.mkIf cfg.enable {
57 system.requiredKernelConfig = [
58 (config.lib.kernelConfig.isEnabled "APPLETALK")
59 ];
60 systemd.services.netatalk.partOf = [ "atalkd.service" ];
61 systemd.services.netatalk.after = interfaces;
62 systemd.services.netatalk.requires = interfaces;
63 systemd.services.atalkd =
64 let
65 interfaces = map (iface: "sys-subsystem-net-devices-${utils.escapeSystemdPath iface}.device") (
66 builtins.attrNames cfg.interfaces
67 );
68 in
69 {
70
71 description = "atalkd AppleTalk daemon";
72 unitConfig.Documentation = "man:atalkd.conf(5) man:atalkd(8)";
73 after = interfaces;
74 wants = [ "network.target" ];
75 before = [ "netatalk.service" ];
76 requires = interfaces;
77
78 wantedBy = [ "multi-user.target" ];
79
80 path = [ pkgs.netatalk ];
81
82 serviceConfig = {
83 Type = "forking";
84 GuessMainPID = "no";
85 DynamicUser = true;
86 AmbientCapabilities = [ "CAP_NET_ADMIN" ];
87 RuntimeDirectory = "atalkd";
88 PIDFile = "/run/atalkd/atalkd";
89 BindPaths = [ "/run/atalkd:/run/lock" ];
90 ExecStart = "${pkgs.netatalk}/bin/atalkd -f ${cfg.configFile}";
91 Restart = "always";
92 };
93 };
94 };
95
96 meta.maintainers = with lib.maintainers; [ matthewcroughan ];
97 meta.doc = ./atalkd.md;
98}