Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / networking / lokinet.nix
blob5c06011822aeeaaa5622fe861e08255c991048bc
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
8 let
9   cfg = config.services.lokinet;
10   dataDir = "/var/lib/lokinet";
11   settingsFormat = pkgs.formats.ini { listsAsDuplicateKeys = true; };
12   configFile = settingsFormat.generate "lokinet.ini" (
13     lib.filterAttrsRecursive (n: v: v != null) cfg.settings
14   );
16 with lib;
18   options.services.lokinet = {
19     enable = mkEnableOption "Lokinet daemon";
21     package = mkPackageOption pkgs "lokinet" { };
23     useLocally = mkOption {
24       type = types.bool;
25       default = false;
26       example = true;
27       description = "Whether to use Lokinet locally.";
28     };
30     settings = mkOption {
31       type =
32         with types;
33         submodule {
34           freeformType = settingsFormat.type;
36           options = {
37             dns = {
38               bind = mkOption {
39                 type = str;
40                 default = "127.3.2.1";
41                 description = "Address to bind to for handling DNS requests.";
42               };
44               upstream = mkOption {
45                 type = listOf str;
46                 default = [ "9.9.9.10" ];
47                 example = [
48                   "1.1.1.1"
49                   "8.8.8.8"
50                 ];
51                 description = ''
52                   Upstream resolver(s) to use as fallback for non-loki addresses.
53                   Multiple values accepted.
54                 '';
55               };
56             };
58             network = {
59               exit = mkOption {
60                 type = bool;
61                 default = false;
62                 description = ''
63                   Whether to act as an exit node. Beware that this
64                   increases demand on the server and may pose liability concerns.
65                   Enable at your own risk.
66                 '';
67               };
69               exit-node = mkOption {
70                 type = nullOr (listOf str);
71                 default = null;
72                 example = ''
73                   exit-node = [ "example.loki" ];              # maps all exit traffic to example.loki
74                   exit-node = [ "example.loki:100.0.0.0/24" ]; # maps 100.0.0.0/24 to example.loki
75                 '';
76                 description = ''
77                   Specify a `.loki` address and an optional ip range to use as an exit broker.
78                   See <http://probably.loki/wiki/index.php?title=Exit_Nodes> for
79                   a list of exit nodes.
80                 '';
81               };
83               keyfile = mkOption {
84                 type = nullOr str;
85                 default = null;
86                 example = "snappkey.private";
87                 description = ''
88                   The private key to persist address with. If not specified the address will be ephemeral.
89                   This keyfile is generated automatically if the specified file doesn't exist.
90                 '';
91               };
92             };
93           };
94         };
95       default = { };
96       example = literalExpression ''
97         {
98           dns = {
99             bind = "127.3.2.1";
100             upstream = [ "1.1.1.1" "8.8.8.8" ];
101           };
103           network.exit-node = [ "example.loki" "example2.loki" ];
104         }
105       '';
106       description = ''
107         Configuration for Lokinet.
108         Currently, the best way to view the available settings is by
109         generating a config file using `lokinet -g`.
110       '';
111     };
112   };
114   config = mkIf cfg.enable {
115     networking.resolvconf.extraConfig = mkIf cfg.useLocally ''
116       name_servers="${cfg.settings.dns.bind}"
117     '';
119     systemd.services.lokinet = {
120       description = "Lokinet";
121       after = [
122         "network-online.target"
123         "network.target"
124       ];
125       wants = [
126         "network-online.target"
127         "network.target"
128       ];
129       wantedBy = [ "multi-user.target" ];
131       preStart = ''
132         ln -sf ${cfg.package}/share/bootstrap.signed ${dataDir}
133         ${pkgs.coreutils}/bin/install -m 600 ${configFile} ${dataDir}/lokinet.ini
135         ${optionalString (cfg.settings.network.keyfile != null) ''
136           ${pkgs.crudini}/bin/crudini --set ${dataDir}/lokinet.ini network keyfile "${dataDir}/${cfg.settings.network.keyfile}"
137         ''}
138       '';
140       serviceConfig = {
141         DynamicUser = true;
142         StateDirectory = "lokinet";
143         AmbientCapabilities = [
144           "CAP_NET_ADMIN"
145           "CAP_NET_BIND_SERVICE"
146         ];
147         ExecStart = "${cfg.package}/bin/lokinet ${dataDir}/lokinet.ini";
148         Restart = "always";
149         RestartSec = "5s";
151         # hardening
152         LockPersonality = true;
153         MemoryDenyWriteExecute = true;
154         NoNewPrivileges = true;
155         PrivateTmp = true;
156         PrivateMounts = true;
157         ProtectControlGroups = true;
158         ProtectHome = true;
159         ProtectHostname = true;
160         ProtectKernelLogs = true;
161         ProtectKernelModules = true;
162         ProtectKernelTunables = true;
163         ProtectSystem = "strict";
164         ReadWritePaths = "/dev/net/tun";
165         RestrictAddressFamilies = [
166           "AF_UNIX"
167           "AF_INET"
168           "AF_INET6"
169           "AF_NETLINK"
170         ];
171         RestrictNamespaces = true;
172         RestrictRealtime = true;
173         RestrictSUIDSGID = true;
174       };
175     };
177     environment.systemPackages = [ cfg.package ];
178   };