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