1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7with lib;
8
9let
10 nncpCfgFile = "/run/nncp.hjson";
11 programCfg = config.programs.nncp;
12 callerCfg = config.services.nncp.caller;
13 daemonCfg = config.services.nncp.daemon;
14 settingsFormat = pkgs.formats.json { };
15 jsonCfgFile = settingsFormat.generate "nncp.json" programCfg.settings;
16 pkg = programCfg.package;
17in
18{
19 options = {
20
21 services.nncp = {
22 caller = {
23 enable = mkEnableOption ''
24 cron'ed NNCP TCP daemon caller.
25 The daemon will take configuration from
26 [](#opt-programs.nncp.settings)
27 '';
28 extraArgs = mkOption {
29 type = with types; listOf str;
30 description = "Extra command-line arguments to pass to caller.";
31 default = [ ];
32 example = [ "-autotoss" ];
33 };
34 };
35
36 daemon = {
37 enable = mkEnableOption ''
38 NNCP TCP synronization daemon.
39 The daemon will take configuration from
40 [](#opt-programs.nncp.settings)
41 '';
42 socketActivation = {
43 enable = mkEnableOption "socket activation for nncp-daemon";
44 listenStreams = mkOption {
45 type = with types; listOf str;
46 description = ''
47 TCP sockets to bind to.
48 See [](#opt-systemd.sockets._name_.listenStreams).
49 '';
50 default = [ "5400" ];
51 };
52 };
53 extraArgs = mkOption {
54 type = with types; listOf str;
55 description = "Extra command-line arguments to pass to daemon.";
56 default = [ ];
57 example = [ "-autotoss" ];
58 };
59 };
60
61 };
62 };
63
64 config = mkIf (programCfg.enable or callerCfg.enable or daemonCfg.enable) {
65
66 assertions = [
67 {
68 assertion =
69 with builtins;
70 let
71 callerCongfigured =
72 let
73 neigh = config.programs.nncp.settings.neigh or { };
74 in
75 lib.lists.any (x: hasAttr "calls" x && x.calls != [ ]) (attrValues neigh);
76 in
77 !callerCfg.enable || callerCongfigured;
78 message = "NNCP caller enabled but call configuration is missing";
79 }
80 ];
81
82 systemd.services."nncp-caller" = {
83 inherit (callerCfg) enable;
84 description = "Croned NNCP TCP daemon caller.";
85 documentation = [ "http://www.nncpgo.org/nncp_002dcaller.html" ];
86 after = [ "network.target" ];
87 wantedBy = [ "multi-user.target" ];
88 serviceConfig = {
89 ExecStart = ''${pkg}/bin/nncp-caller -noprogress -cfg "${nncpCfgFile}" ${lib.strings.escapeShellArgs callerCfg.extraArgs}'';
90 Group = "uucp";
91 UMask = "0002";
92 };
93 };
94
95 systemd.services."nncp-daemon" = mkIf daemonCfg.enable {
96 enable = !daemonCfg.socketActivation.enable;
97 description = "NNCP TCP syncronization daemon.";
98 documentation = [ "http://www.nncpgo.org/nncp_002ddaemon.html" ];
99 after = [ "network.target" ];
100 wantedBy = [ "multi-user.target" ];
101 serviceConfig = {
102 ExecStart = ''${pkg}/bin/nncp-daemon -noprogress -cfg "${nncpCfgFile}" ${lib.strings.escapeShellArgs daemonCfg.extraArgs}'';
103 Restart = "on-failure";
104 Group = "uucp";
105 UMask = "0002";
106 };
107 };
108
109 systemd.services."nncp-daemon@" = mkIf daemonCfg.socketActivation.enable {
110 description = "NNCP TCP syncronization daemon.";
111 documentation = [ "http://www.nncpgo.org/nncp_002ddaemon.html" ];
112 after = [ "network.target" ];
113 serviceConfig = {
114 ExecStart = ''${pkg}/bin/nncp-daemon -noprogress -ucspi -cfg "${nncpCfgFile}" ${lib.strings.escapeShellArgs daemonCfg.extraArgs}'';
115 Group = "uucp";
116 UMask = "0002";
117 StandardInput = "socket";
118 StandardOutput = "inherit";
119 StandardError = "journal";
120 };
121 };
122
123 systemd.sockets.nncp-daemon = mkIf daemonCfg.socketActivation.enable {
124 inherit (daemonCfg.socketActivation) listenStreams;
125 description = "socket for NNCP TCP syncronization.";
126 conflicts = [ "nncp-daemon.service" ];
127 wantedBy = [ "sockets.target" ];
128 socketConfig.Accept = true;
129 };
130 };
131}