python312Packages.mandown: 1.10.0 -> 1.10.1 (#370595)
[NixPkgs.git] / nixos / modules / services / networking / spiped.nix
blob09d8156d1c510df449dc0e46416a6d6614462d24
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.spiped;
7 in
9   options = {
10     services.spiped = {
11       enable = mkOption {
12         type        = types.bool;
13         default     = false;
14         description = "Enable the spiped service module.";
15       };
17       config = mkOption {
18         type = types.attrsOf (types.submodule (
19           {
20             options = {
21               encrypt = mkOption {
22                 type    = types.bool;
23                 default = false;
24                 description = ''
25                   Take unencrypted connections from the
26                   `source` socket and send encrypted
27                   connections to the `target` socket.
28                 '';
29               };
31               decrypt = mkOption {
32                 type    = types.bool;
33                 default = false;
34                 description = ''
35                   Take encrypted connections from the
36                   `source` socket and send unencrypted
37                   connections to the `target` socket.
38                 '';
39               };
41               source = mkOption {
42                 type    = types.str;
43                 description = ''
44                   Address on which spiped should listen for incoming
45                   connections.  Must be in one of the following formats:
46                   `/absolute/path/to/unix/socket`,
47                   `host.name:port`,
48                   `[ip.v4.ad.dr]:port` or
49                   `[ipv6::addr]:port` - note that
50                   hostnames are resolved when spiped is launched and are
51                   not re-resolved later; thus if DNS entries change
52                   spiped will continue to connect to the expired
53                   address.
54                 '';
55               };
57               target = mkOption {
58                 type    = types.str;
59                 description = "Address to which spiped should connect.";
60               };
62               keyfile = mkOption {
63                 type    = types.path;
64                 description = ''
65                   Name of a file containing the spiped key.
66                   As the daemon runs as the `spiped` user,
67                   the key file must be readable by that user.
68                   To securely manage the file within your configuration
69                   consider a tool such as agenix or sops-nix.
70                 '';
71               };
73               timeout = mkOption {
74                 type = types.int;
75                 default = 5;
76                 description = ''
77                   Timeout, in seconds, after which an attempt to connect to
78                   the target or a protocol handshake will be aborted (and the
79                   connection dropped) if not completed
80                 '';
81               };
83               maxConns = mkOption {
84                 type = types.int;
85                 default = 100;
86                 description = ''
87                   Limit on the number of simultaneous connections allowed.
88                 '';
89               };
91               waitForDNS = mkOption {
92                 type = types.bool;
93                 default = false;
94                 description = ''
95                   Wait for DNS. Normally when `spiped` is
96                   launched it resolves addresses and binds to its source
97                   socket before the parent process returns; with this option
98                   it will daemonize first and retry failed DNS lookups until
99                   they succeed. This allows `spiped` to
100                   launch even if DNS isn't set up yet, but at the expense of
101                   losing the guarantee that once `spiped` has
102                   finished launching it will be ready to create pipes.
103                 '';
104               };
106               disableKeepalives = mkOption {
107                 type = types.bool;
108                 default = false;
109                 description = "Disable transport layer keep-alives.";
110               };
112               weakHandshake = mkOption {
113                 type = types.bool;
114                 default = false;
115                 description = ''
116                   Use fast/weak handshaking: This reduces the CPU time spent
117                   in the initial connection setup, at the expense of losing
118                   perfect forward secrecy.
119                 '';
120               };
122               resolveRefresh = mkOption {
123                 type = types.int;
124                 default = 60;
125                 description = ''
126                   Resolution refresh time for the target socket, in seconds.
127                 '';
128               };
130               disableReresolution = mkOption {
131                 type = types.bool;
132                 default = false;
133                 description = "Disable target address re-resolution.";
134               };
135             };
136           }
137         ));
139         default = {};
141         example = literalExpression ''
142           {
143             pipe1 =
144               { keyfile = "/var/lib/spiped/pipe1.key";
145                 encrypt = true;
146                 source  = "localhost:6000";
147                 target  = "endpoint.example.com:7000";
148               };
149             pipe2 =
150               { keyfile = "/var/lib/spiped/pipe2.key";
151                 decrypt = true;
152                 source  = "0.0.0.0:7000";
153                 target  = "localhost:3000";
154               };
155           }
156         '';
158         description = ''
159           Configuration for a secure pipe daemon. The daemon can be
160           started, stopped, or examined using
161           `systemctl`, under the name
162           `spiped@foo`.
163         '';
164       };
165     };
166   };
168   config = mkIf cfg.enable {
169     assertions = mapAttrsToList (name: c: {
170       assertion = (c.encrypt -> !c.decrypt) || (c.decrypt -> c.encrypt);
171       message   = "A pipe must either encrypt or decrypt";
172     }) cfg.config;
174     users.groups.spiped.gid = config.ids.gids.spiped;
175     users.users.spiped = {
176       description = "Secure Pipe Service user";
177       group       = "spiped";
178       uid         = config.ids.uids.spiped;
179     };
181     systemd.services."spiped@" = {
182       description = "Secure pipe '%i'";
183       after       = [ "network.target" ];
185       serviceConfig = {
186         Restart   = "always";
187         User      = "spiped";
188       };
189       stopIfChanged = false;
191       scriptArgs = "%i";
192       script = "exec ${pkgs.spiped}/bin/spiped -F `cat /etc/spiped/$1.spec`";
193     };
195     # Setup spiped config files
196     environment.etc = mapAttrs' (name: cfg: nameValuePair "spiped/${name}.spec"
197       { text = concatStringsSep " "
198           [ (if cfg.encrypt then "-e" else "-d")        # Mode
199             "-s ${cfg.source}"                          # Source
200             "-t ${cfg.target}"                          # Target
201             "-k ${cfg.keyfile}"                         # Keyfile
202             "-n ${toString cfg.maxConns}"               # Max number of conns
203             "-o ${toString cfg.timeout}"                # Timeout
204             (optionalString cfg.waitForDNS "-D")        # Wait for DNS
205             (optionalString cfg.weakHandshake "-f")     # No PFS
206             (optionalString cfg.disableKeepalives "-j") # Keepalives
207             (if cfg.disableReresolution then "-R"
208               else "-r ${toString cfg.resolveRefresh}")
209           ];
210       }) cfg.config;
211   };