at 23.11-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 Explicitly 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 ReadWritePaths = [ cfg.beacon.dataDir ]; 251 NoNewPrivileges = true; 252 PrivateTmp = true; 253 ProtectHome = true; 254 ProtectClock = true; 255 ProtectProc = "noaccess"; 256 ProcSubset = "pid"; 257 ProtectKernelLogs = true; 258 ProtectKernelModules = true; 259 ProtectKernelTunables = true; 260 ProtectControlGroups = true; 261 ProtectHostname = true; 262 RestrictSUIDSGID = true; 263 RestrictRealtime = true; 264 RestrictNamespaces = true; 265 LockPersonality = true; 266 RemoveIPC = true; 267 SystemCallFilter = [ "@system-service" "~@privileged" ]; 268 }; 269 }; 270 271 systemd.services.lighthouse-validator = mkIf cfg.validator.enable { 272 description = "Lighthouse validtor node (manages validators, using data obtained from the beacon node via a HTTP API)"; 273 wantedBy = [ "multi-user.target" ]; 274 after = [ "network.target" ]; 275 276 script = '' 277 # make sure the chain data directory is created on first run 278 mkdir -p ${cfg.validator.dataDir}/${cfg.network} 279 280 ${pkgs.lighthouse}/bin/lighthouse validator_client \ 281 --network ${cfg.network} \ 282 --beacon-nodes ${lib.concatStringsSep "," cfg.validator.beaconNodes} \ 283 --datadir ${cfg.validator.dataDir}/${cfg.network} \ 284 ${optionalString cfg.validator.metrics.enable ''--metrics --metrics-address ${cfg.validator.metrics.address} --metrics-port ${toString cfg.validator.metrics.port}''} \ 285 ${cfg.extraArgs} ${cfg.validator.extraArgs} 286 ''; 287 288 serviceConfig = { 289 Restart = "on-failure"; 290 StateDirectory = "lighthouse-validator"; 291 ReadWritePaths = [ cfg.validator.dataDir ]; 292 CapabilityBoundingSet = ""; 293 DynamicUser = true; 294 NoNewPrivileges = true; 295 PrivateTmp = true; 296 ProtectHome = true; 297 ProtectClock = true; 298 ProtectProc = "noaccess"; 299 ProcSubset = "pid"; 300 ProtectKernelLogs = true; 301 ProtectKernelModules = true; 302 ProtectKernelTunables = true; 303 ProtectControlGroups = true; 304 ProtectHostname = true; 305 RestrictSUIDSGID = true; 306 RestrictRealtime = true; 307 RestrictNamespaces = true; 308 LockPersonality = true; 309 RemoveIPC = true; 310 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; 311 SystemCallFilter = [ "@system-service" "~@privileged" ]; 312 }; 313 }; 314 }; 315}