at 23.05-pre 11 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4let 5 6 cfg = config.services.lighthouse; 7in { 8 9 options = { 10 services.lighthouse = { 11 beacon = mkOption { 12 description = lib.mdDoc "Beacon node"; 13 default = {}; 14 type = types.submodule { 15 options = { 16 enable = lib.mkEnableOption (lib.mdDoc "Lightouse Beacon node"); 17 18 dataDir = mkOption { 19 type = types.str; 20 default = "/var/lib/lighthouse-beacon"; 21 description = lib.mdDoc '' 22 Directory where data will be stored. Each chain will be stored under it's own specific subdirectory. 23 ''; 24 }; 25 26 address = mkOption { 27 type = types.str; 28 default = "0.0.0.0"; 29 description = lib.mdDoc '' 30 Listen address of Beacon node. 31 ''; 32 }; 33 34 port = mkOption { 35 type = types.port; 36 default = 9000; 37 description = lib.mdDoc '' 38 Port number the Beacon node will be listening on. 39 ''; 40 }; 41 42 openFirewall = mkOption { 43 type = types.bool; 44 default = false; 45 description = lib.mdDoc '' 46 Open the port in the firewall 47 ''; 48 }; 49 50 disableDepositContractSync = mkOption { 51 type = types.bool; 52 default = false; 53 description = lib.mdDoc '' 54 Explictly disables syncing of deposit logs from the execution node. 55 This overrides any previous option that depends on it. 56 Useful if you intend to run a non-validating beacon node. 57 ''; 58 }; 59 60 execution = { 61 address = mkOption { 62 type = types.str; 63 default = "127.0.0.1"; 64 description = lib.mdDoc '' 65 Listen address for the execution layer. 66 ''; 67 }; 68 69 port = mkOption { 70 type = types.port; 71 default = 8551; 72 description = lib.mdDoc '' 73 Port number the Beacon node will be listening on for the execution layer. 74 ''; 75 }; 76 77 jwtPath = mkOption { 78 type = types.str; 79 default = ""; 80 description = lib.mdDoc '' 81 Path for the jwt secret required to connect to the execution layer. 82 ''; 83 }; 84 }; 85 86 http = { 87 enable = lib.mkEnableOption (lib.mdDoc "Beacon node http api"); 88 port = mkOption { 89 type = types.port; 90 default = 5052; 91 description = lib.mdDoc '' 92 Port number of Beacon node RPC service. 93 ''; 94 }; 95 96 address = mkOption { 97 type = types.str; 98 default = "127.0.0.1"; 99 description = lib.mdDoc '' 100 Listen address of Beacon node RPC service. 101 ''; 102 }; 103 }; 104 105 metrics = { 106 enable = lib.mkEnableOption (lib.mdDoc "Beacon node prometheus metrics"); 107 address = mkOption { 108 type = types.str; 109 default = "127.0.0.1"; 110 description = lib.mdDoc '' 111 Listen address of Beacon node metrics service. 112 ''; 113 }; 114 115 port = mkOption { 116 type = types.port; 117 default = 5054; 118 description = lib.mdDoc '' 119 Port number of Beacon node metrics service. 120 ''; 121 }; 122 }; 123 124 extraArgs = mkOption { 125 type = types.str; 126 description = lib.mdDoc '' 127 Additional arguments passed to the lighthouse beacon command. 128 ''; 129 default = ""; 130 example = ""; 131 }; 132 }; 133 }; 134 }; 135 136 validator = mkOption { 137 description = lib.mdDoc "Validator node"; 138 default = {}; 139 type = types.submodule { 140 options = { 141 enable = mkOption { 142 type = types.bool; 143 default = false; 144 description = lib.mdDoc "Enable Lightouse Validator node."; 145 }; 146 147 dataDir = mkOption { 148 type = types.str; 149 default = "/var/lib/lighthouse-validator"; 150 description = lib.mdDoc '' 151 Directory where data will be stored. Each chain will be stored under it's own specific subdirectory. 152 ''; 153 }; 154 155 beaconNodes = mkOption { 156 type = types.listOf types.str; 157 default = ["http://localhost:5052"]; 158 description = lib.mdDoc '' 159 Beacon nodes to connect to. 160 ''; 161 }; 162 163 metrics = { 164 enable = lib.mkEnableOption (lib.mdDoc "Validator node prometheus metrics"); 165 address = mkOption { 166 type = types.str; 167 default = "127.0.0.1"; 168 description = lib.mdDoc '' 169 Listen address of Validator node metrics service. 170 ''; 171 }; 172 173 port = mkOption { 174 type = types.port; 175 default = 5056; 176 description = lib.mdDoc '' 177 Port number of Validator node metrics service. 178 ''; 179 }; 180 }; 181 182 extraArgs = mkOption { 183 type = types.str; 184 description = lib.mdDoc '' 185 Additional arguments passed to the lighthouse validator command. 186 ''; 187 default = ""; 188 example = ""; 189 }; 190 }; 191 }; 192 }; 193 194 network = mkOption { 195 type = types.enum [ "mainnet" "prater" "goerli" "gnosis" "kiln" "ropsten" "sepolia" ]; 196 default = "mainnet"; 197 description = lib.mdDoc '' 198 The network to connect to. Mainnet is the default ethereum network. 199 ''; 200 }; 201 202 extraArgs = mkOption { 203 type = types.str; 204 description = lib.mdDoc '' 205 Additional arguments passed to every lighthouse command. 206 ''; 207 default = ""; 208 example = ""; 209 }; 210 }; 211 }; 212 213 config = mkIf (cfg.beacon.enable || cfg.validator.enable) { 214 215 environment.systemPackages = [ pkgs.lighthouse ] ; 216 217 networking.firewall = mkIf cfg.beacon.enable { 218 allowedTCPPorts = mkIf cfg.beacon.openFirewall [ cfg.beacon.port ]; 219 allowedUDPPorts = mkIf cfg.beacon.openFirewall [ cfg.beacon.port ]; 220 }; 221 222 223 systemd.services.lighthouse-beacon = mkIf cfg.beacon.enable { 224 description = "Lighthouse beacon node (connect to P2P nodes and verify blocks)"; 225 wantedBy = [ "multi-user.target" ]; 226 after = [ "network.target" ]; 227 228 script = '' 229 # make sure the chain data directory is created on first run 230 mkdir -p ${cfg.beacon.dataDir}/${cfg.network} 231 232 ${pkgs.lighthouse}/bin/lighthouse beacon_node \ 233 --disable-upnp \ 234 ${lib.optionalString cfg.beacon.disableDepositContractSync "--disable-deposit-contract-sync"} \ 235 --port ${toString cfg.beacon.port} \ 236 --listen-address ${cfg.beacon.address} \ 237 --network ${cfg.network} \ 238 --datadir ${cfg.beacon.dataDir}/${cfg.network} \ 239 --execution-endpoint http://${cfg.beacon.execution.address}:${toString cfg.beacon.execution.port} \ 240 --execution-jwt ''${CREDENTIALS_DIRECTORY}/LIGHTHOUSE_JWT \ 241 ${lib.optionalString cfg.beacon.http.enable '' --http --http-address ${cfg.beacon.http.address} --http-port ${toString cfg.beacon.http.port}''} \ 242 ${lib.optionalString cfg.beacon.metrics.enable '' --metrics --metrics-address ${cfg.beacon.metrics.address} --metrics-port ${toString cfg.beacon.metrics.port}''} \ 243 ${cfg.extraArgs} ${cfg.beacon.extraArgs} 244 ''; 245 serviceConfig = { 246 LoadCredential = "LIGHTHOUSE_JWT:${cfg.beacon.execution.jwtPath}"; 247 DynamicUser = true; 248 Restart = "on-failure"; 249 StateDirectory = "lighthouse-beacon"; 250 NoNewPrivileges = true; 251 PrivateTmp = true; 252 ProtectHome = true; 253 ProtectClock = true; 254 ProtectProc = "noaccess"; 255 ProcSubset = "pid"; 256 ProtectKernelLogs = true; 257 ProtectKernelModules = true; 258 ProtectKernelTunables = true; 259 ProtectControlGroups = true; 260 ProtectHostname = true; 261 RestrictSUIDSGID = true; 262 RestrictRealtime = true; 263 RestrictNamespaces = true; 264 LockPersonality = true; 265 RemoveIPC = true; 266 SystemCallFilter = [ "@system-service" "~@privileged" ]; 267 }; 268 }; 269 270 systemd.services.lighthouse-validator = mkIf cfg.validator.enable { 271 description = "Lighthouse validtor node (manages validators, using data obtained from the beacon node via a HTTP API)"; 272 wantedBy = [ "multi-user.target" ]; 273 after = [ "network.target" ]; 274 275 script = '' 276 # make sure the chain data directory is created on first run 277 mkdir -p ${cfg.validator.dataDir}/${cfg.network} 278 279 ${pkgs.lighthouse}/bin/lighthouse validator_client \ 280 --network ${cfg.network} \ 281 --beacon-nodes ${lib.concatStringsSep "," cfg.validator.beaconNodes} \ 282 --datadir ${cfg.validator.dataDir}/${cfg.network} 283 ${optionalString cfg.validator.metrics.enable ''--metrics --metrics-address ${cfg.validator.metrics.address} --metrics-port ${toString cfg.validator.metrics.port}''} \ 284 ${cfg.extraArgs} ${cfg.validator.extraArgs} 285 ''; 286 287 serviceConfig = { 288 Restart = "on-failure"; 289 StateDirectory = "lighthouse-validator"; 290 CapabilityBoundingSet = ""; 291 DynamicUser = true; 292 NoNewPrivileges = true; 293 PrivateTmp = true; 294 ProtectHome = true; 295 ProtectClock = true; 296 ProtectProc = "noaccess"; 297 ProcSubset = "pid"; 298 ProtectKernelLogs = true; 299 ProtectKernelModules = true; 300 ProtectKernelTunables = true; 301 ProtectControlGroups = true; 302 ProtectHostname = true; 303 RestrictSUIDSGID = true; 304 RestrictRealtime = true; 305 RestrictNamespaces = true; 306 LockPersonality = true; 307 RemoveIPC = true; 308 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; 309 SystemCallFilter = [ "@system-service" "~@privileged" ]; 310 }; 311 }; 312 }; 313}