1 { config, lib, pkgs, ... }:
4 cfg = config.services.lokinet;
5 dataDir = "/var/lib/lokinet";
6 settingsFormat = pkgs.formats.ini { listsAsDuplicateKeys = true; };
7 configFile = settingsFormat.generate "lokinet.ini" (lib.filterAttrsRecursive (n: v: v != null) cfg.settings);
9 options.services.lokinet = {
10 enable = mkEnableOption "Lokinet daemon";
12 package = mkPackageOption pkgs "lokinet" { };
14 useLocally = mkOption {
18 description = "Whether to use Lokinet locally.";
24 freeformType = settingsFormat.type;
30 default = "127.3.2.1";
31 description = "Address to bind to for handling DNS requests.";
36 default = [ "9.9.9.10" ];
37 example = [ "1.1.1.1" "8.8.8.8" ];
39 Upstream resolver(s) to use as fallback for non-loki addresses.
40 Multiple values accepted.
50 Whether to act as an exit node. Beware that this
51 increases demand on the server and may pose liability concerns.
52 Enable at your own risk.
56 exit-node = mkOption {
57 type = nullOr (listOf str);
60 exit-node = [ "example.loki" ]; # maps all exit traffic to example.loki
61 exit-node = [ "example.loki:100.0.0.0/24" ]; # maps 100.0.0.0/24 to example.loki
64 Specify a `.loki` address and an optional ip range to use as an exit broker.
65 See <http://probably.loki/wiki/index.php?title=Exit_Nodes> for
73 example = "snappkey.private";
75 The private key to persist address with. If not specified the address will be ephemeral.
76 This keyfile is generated automatically if the specified file doesn't exist.
83 example = literalExpression ''
87 upstream = [ "1.1.1.1" "8.8.8.8" ];
90 network.exit-node = [ "example.loki" "example2.loki" ];
94 Configuration for Lokinet.
95 Currently, the best way to view the available settings is by
96 generating a config file using `lokinet -g`.
101 config = mkIf cfg.enable {
102 networking.resolvconf.extraConfig = mkIf cfg.useLocally ''
103 name_servers="${cfg.settings.dns.bind}"
106 systemd.services.lokinet = {
107 description = "Lokinet";
108 after = [ "network-online.target" "network.target" ];
109 wants = [ "network-online.target" "network.target" ];
110 wantedBy = [ "multi-user.target" ];
113 ln -sf ${cfg.package}/share/bootstrap.signed ${dataDir}
114 ${pkgs.coreutils}/bin/install -m 600 ${configFile} ${dataDir}/lokinet.ini
116 ${optionalString (cfg.settings.network.keyfile != null) ''
117 ${pkgs.crudini}/bin/crudini --set ${dataDir}/lokinet.ini network keyfile "${dataDir}/${cfg.settings.network.keyfile}"
123 StateDirectory = "lokinet";
124 AmbientCapabilities = [ "CAP_NET_ADMIN" "CAP_NET_BIND_SERVICE" ];
125 ExecStart = "${cfg.package}/bin/lokinet ${dataDir}/lokinet.ini";
130 LockPersonality = true;
131 MemoryDenyWriteExecute = true;
132 NoNewPrivileges = true;
134 PrivateMounts = true;
135 ProtectControlGroups = true;
137 ProtectHostname = true;
138 ProtectKernelLogs = true;
139 ProtectKernelModules = true;
140 ProtectKernelTunables = true;
141 ProtectSystem = "strict";
142 ReadWritePaths = "/dev/net/tun";
143 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK" ];
144 RestrictNamespaces = true;
145 RestrictRealtime = true;
146 RestrictSUIDSGID = true;
150 environment.systemPackages = [ cfg.package ];