1 # NixOS module for iodine, ip over dns daemon
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;
18 (lib.mkRenamedOptionModule
19 [ "services" "iodined" "enable" ]
20 [ "services" "iodine" "server" "enable" ]
22 (lib.mkRenamedOptionModule
23 [ "services" "iodined" "domain" ]
24 [ "services" "iodine" "server" "domain" ]
26 (lib.mkRenamedOptionModule [ "services" "iodined" "ip" ] [ "services" "iodine" "server" "ip" ])
27 (lib.mkRenamedOptionModule
28 [ "services" "iodined" "extraConfig" ]
29 [ "services" "iodine" "server" "extraConfig" ]
31 (lib.mkRemovedOptionModule [ "services" "iodined" "client" ] "")
39 clients = lib.mkOption {
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
46 where «name» is the name of the
47 corresponding attribute name.
49 example = lib.literalExpression ''
52 server = "tunnel.mdomain.com";
58 type = lib.types.attrsOf (
59 lib.types.submodule ({
61 server = lib.mkOption {
64 description = "Hostname of server running iodined";
65 example = "tunnel.mydomain.com";
68 relay = lib.mkOption {
71 description = "DNS server to use as an intermediate relay to the iodined server";
75 extraConfig = lib.mkOption {
78 description = "Additional command line parameters";
79 example = "-l 192.168.1.10 -p 23";
82 passwordFile = lib.mkOption {
85 description = "Path to a file containing the password.";
93 enable = lib.mkOption {
94 type = lib.types.bool;
96 description = "enable iodined server";
100 type = lib.types.str;
102 description = "The assigned ip address or ip range";
103 example = "172.16.10.1/24";
106 domain = lib.mkOption {
107 type = lib.types.str;
109 description = "Domain or subdomain of which nameservers point to us";
110 example = "tunnel.mydomain.com";
113 extraConfig = lib.mkOption {
114 type = lib.types.str;
116 description = "Additional command line parameters";
117 example = "-l 192.168.1.10 -p 23";
120 passwordFile = lib.mkOption {
121 type = lib.types.str;
123 description = "File that contains password";
132 config = lib.mkIf (cfg.server.enable || cfg.clients != { }) {
133 environment.systemPackages = [ pkgs.iodine ];
134 boot.kernelModules = [ "tun" ];
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}";
151 ProtectSystem = "strict";
152 ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true";
154 ReadWritePaths = "/dev/net/tun";
155 PrivateDevices = false;
156 ProtectKernelTunables = true;
157 ProtectKernelModules = true;
158 ProtectControlGroups = true;
160 NoNewPrivileges = true;
162 LockPersonality = true;
163 RestrictRealtime = true;
164 PrivateMounts = true;
165 MemoryDenyWriteExecute = true;
171 name: value: lib.nameValuePair "iodine-${name}" (createIodineClientService name value)
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} ${
181 cfg.server.passwordFile != ""
182 ) "< \"${builtins.toString cfg.server.passwordFile}\""
183 } ${cfg.server.ip} ${cfg.server.domain}";
186 ProtectSystem = "strict";
187 ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true";
189 ReadWritePaths = "/dev/net/tun";
190 PrivateDevices = false;
191 ProtectKernelTunables = true;
192 ProtectKernelModules = true;
193 ProtectControlGroups = true;
195 NoNewPrivileges = true;
197 LockPersonality = true;
198 RestrictRealtime = true;
199 PrivateMounts = true;
200 MemoryDenyWriteExecute = true;
205 users.users.${iodinedUser} = {
206 uid = config.ids.uids.iodined;
208 description = "Iodine daemon user";
210 users.groups.iodined.gid = config.ids.gids.iodined;