at 25.11-pre 5.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 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 ); 15in 16with lib; 17{ 18 options.services.lokinet = { 19 enable = mkEnableOption "Lokinet daemon"; 20 21 package = mkPackageOption pkgs "lokinet" { }; 22 23 useLocally = mkOption { 24 type = types.bool; 25 default = false; 26 example = true; 27 description = "Whether to use Lokinet locally."; 28 }; 29 30 settings = mkOption { 31 type = 32 with types; 33 submodule { 34 freeformType = settingsFormat.type; 35 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 }; 43 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 }; 57 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 }; 68 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 }; 82 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 }; 102 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 }; 113 114 config = mkIf cfg.enable { 115 networking.resolvconf.extraConfig = mkIf cfg.useLocally '' 116 name_servers="${cfg.settings.dns.bind}" 117 ''; 118 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" ]; 130 131 preStart = '' 132 ln -sf ${cfg.package}/share/bootstrap.signed ${dataDir} 133 ${pkgs.coreutils}/bin/install -m 600 ${configFile} ${dataDir}/lokinet.ini 134 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 ''; 139 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"; 150 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 }; 176 177 environment.systemPackages = [ cfg.package ]; 178 }; 179}