Remove n0emis as direct maintainer (#365023)
[NixPkgs.git] / nixos / modules / services / networking / iodine.nix
blobed3ff28cd5f4d32a89c17fbd8ea32c4b05d26001
1 # NixOS module for iodine, ip over dns daemon
3   config,
4   lib,
5   pkgs,
6   ...
7 }:
8 let
9   cfg = config.services.iodine;
11   iodinedUser = "iodined";
13   # is this path made unreadable by ProtectHome = true ?
14   isProtected = x: lib.hasPrefix "/root" x || lib.hasPrefix "/home" x;
17   imports = [
18     (lib.mkRenamedOptionModule
19       [ "services" "iodined" "enable" ]
20       [ "services" "iodine" "server" "enable" ]
21     )
22     (lib.mkRenamedOptionModule
23       [ "services" "iodined" "domain" ]
24       [ "services" "iodine" "server" "domain" ]
25     )
26     (lib.mkRenamedOptionModule [ "services" "iodined" "ip" ] [ "services" "iodine" "server" "ip" ])
27     (lib.mkRenamedOptionModule
28       [ "services" "iodined" "extraConfig" ]
29       [ "services" "iodine" "server" "extraConfig" ]
30     )
31     (lib.mkRemovedOptionModule [ "services" "iodined" "client" ] "")
32   ];
34   ### configuration
36   options = {
38     services.iodine = {
39       clients = lib.mkOption {
40         default = { };
41         description = ''
42           Each attribute of this option defines a systemd service that
43           runs iodine. Many or none may be defined.
44           The name of each service is
45           `iodine-«name»`
46           where «name» is the name of the
47           corresponding attribute name.
48         '';
49         example = lib.literalExpression ''
50           {
51             foo = {
52               server = "tunnel.mdomain.com";
53               relay = "8.8.8.8";
54               extraConfig = "-v";
55             }
56           }
57         '';
58         type = lib.types.attrsOf (
59           lib.types.submodule ({
60             options = {
61               server = lib.mkOption {
62                 type = lib.types.str;
63                 default = "";
64                 description = "Hostname of server running iodined";
65                 example = "tunnel.mydomain.com";
66               };
68               relay = lib.mkOption {
69                 type = lib.types.str;
70                 default = "";
71                 description = "DNS server to use as an intermediate relay to the iodined server";
72                 example = "8.8.8.8";
73               };
75               extraConfig = lib.mkOption {
76                 type = lib.types.str;
77                 default = "";
78                 description = "Additional command line parameters";
79                 example = "-l 192.168.1.10 -p 23";
80               };
82               passwordFile = lib.mkOption {
83                 type = lib.types.str;
84                 default = "";
85                 description = "Path to a file containing the password.";
86               };
87             };
88           })
89         );
90       };
92       server = {
93         enable = lib.mkOption {
94           type = lib.types.bool;
95           default = false;
96           description = "enable iodined server";
97         };
99         ip = lib.mkOption {
100           type = lib.types.str;
101           default = "";
102           description = "The assigned ip address or ip range";
103           example = "172.16.10.1/24";
104         };
106         domain = lib.mkOption {
107           type = lib.types.str;
108           default = "";
109           description = "Domain or subdomain of which nameservers point to us";
110           example = "tunnel.mydomain.com";
111         };
113         extraConfig = lib.mkOption {
114           type = lib.types.str;
115           default = "";
116           description = "Additional command line parameters";
117           example = "-l 192.168.1.10 -p 23";
118         };
120         passwordFile = lib.mkOption {
121           type = lib.types.str;
122           default = "";
123           description = "File that contains password";
124         };
125       };
127     };
128   };
130   ### implementation
132   config = lib.mkIf (cfg.server.enable || cfg.clients != { }) {
133     environment.systemPackages = [ pkgs.iodine ];
134     boot.kernelModules = [ "tun" ];
136     systemd.services =
137       let
138         createIodineClientService = name: cfg: {
139           description = "iodine client - ${name}";
140           after = [ "network.target" ];
141           wantedBy = [ "multi-user.target" ];
142           script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${
143             lib.optionalString (cfg.passwordFile != "") "< \"${builtins.toString cfg.passwordFile}\""
144           } ${cfg.relay} ${cfg.server}";
145           serviceConfig = {
146             RestartSec = "30s";
147             Restart = "always";
149             # hardening :
150             # Filesystem access
151             ProtectSystem = "strict";
152             ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true";
153             PrivateTmp = true;
154             ReadWritePaths = "/dev/net/tun";
155             PrivateDevices = false;
156             ProtectKernelTunables = true;
157             ProtectKernelModules = true;
158             ProtectControlGroups = true;
159             # Caps
160             NoNewPrivileges = true;
161             # Misc.
162             LockPersonality = true;
163             RestrictRealtime = true;
164             PrivateMounts = true;
165             MemoryDenyWriteExecute = true;
166           };
167         };
168       in
169       lib.listToAttrs (
170         lib.mapAttrsToList (
171           name: value: lib.nameValuePair "iodine-${name}" (createIodineClientService name value)
172         ) cfg.clients
173       )
174       // {
175         iodined = lib.mkIf (cfg.server.enable) {
176           description = "iodine, ip over dns server daemon";
177           after = [ "network.target" ];
178           wantedBy = [ "multi-user.target" ];
179           script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${
180             lib.optionalString (
181               cfg.server.passwordFile != ""
182             ) "< \"${builtins.toString cfg.server.passwordFile}\""
183           } ${cfg.server.ip} ${cfg.server.domain}";
184           serviceConfig = {
185             # Filesystem access
186             ProtectSystem = "strict";
187             ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true";
188             PrivateTmp = true;
189             ReadWritePaths = "/dev/net/tun";
190             PrivateDevices = false;
191             ProtectKernelTunables = true;
192             ProtectKernelModules = true;
193             ProtectControlGroups = true;
194             # Caps
195             NoNewPrivileges = true;
196             # Misc.
197             LockPersonality = true;
198             RestrictRealtime = true;
199             PrivateMounts = true;
200             MemoryDenyWriteExecute = true;
201           };
202         };
203       };
205     users.users.${iodinedUser} = {
206       uid = config.ids.uids.iodined;
207       group = "iodined";
208       description = "Iodine daemon user";
209     };
210     users.groups.iodined.gid = config.ids.gids.iodined;
211   };