-
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement Nimbus beacon service (#434)
Implement Nimbus Beacon service
- Loading branch information
Showing
6 changed files
with
510 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Running Nimbus Beacon | ||
|
||
One or more [Nimbus Beacon](https://nimbus.guide) services can be configured with the `services.ethereum.nimbus-beacon` prefix. | ||
|
||
```nix title="server.nix" | ||
{ pkgs, ...}: { | ||
services.ethereum.nimbus-beacon.mainnet = { | ||
enable = true; | ||
openFirewall = true; | ||
args = { | ||
network = "mainnet"; | ||
jwt-secret = secrets.nimbus_jwt_secret.path; | ||
trusted-node-url = "https://sync.invis.tools"; | ||
rest.enable = true; | ||
}; | ||
}; | ||
}; | ||
} | ||
``` | ||
|
||
**Note:** It is recommended to use an attribute name that matches the network that Nimbus Beacon is configured for. Unless the [network](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameargsnetwork) option is set, the Nimbus Beacon node network will default to the name, eg. `services.ethereum.nimbus-beacon.mainnet` will connect to Ethereum mainnet. | ||
|
||
## Configuration | ||
|
||
Many of Nimbus's process arguments have been mapped to NixOS types and can be provided via the `args` section of the config. | ||
For a detailed list please refer to the [NixOS Options](./modules/nimbus-beacon.md) reference. | ||
|
||
Additional arguments can be provided in a list directly to the Nimbus Beacon process via the `extraArgs` attribute as shown above. | ||
|
||
## Systemd service | ||
|
||
For each instance that is configured a corresponding [Systemd](https://systemd.io/) service is created. The service name | ||
follows a convention of `nimbus-beacon-${name}.service`. | ||
|
||
| Config | Name | Service name | | ||
| :-------------------------------------------- | :------ | :---------------------------------- | | ||
| `services.ethereum.nimbus-beacon.sepolia` | sepolia | `nimbus-beacon-sepolia.service` | | ||
| `services.ethereum.nimbus-beacon.holesky` | holesky | `nimbus-beacon-holesky.service` | | ||
| `services.ethereum.nimbus-beacon.mainnet` | mainnet | `nimbus-beacon-mainnet.service` | | ||
|
||
The service that is created can then be introspected and managed via the standard Systemd toolset. | ||
|
||
| Action | Command | | ||
| :------ | :---------------------------------------------------- | | ||
| Status | `systemctl status nimbus-beacon-sepolia.service` | | ||
| Stop | `systemctl stop nimbus-beacon-sepolia.service` | | ||
| Start | `systemctl start nimbus-beacon-sepolia.service` | | ||
| Restart | `systemctl restart nimbus-beacon-sepolia.service` | | ||
| Logs | `journalctl -xefu nimbus-beacon-sepolia.service` | | ||
|
||
## Checkpoint Sync | ||
|
||
Nimbus can be configured to checkpoint sync from a trusted beacon node URL using the [trusted-node-url](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameargstrusted-node-url) option. See [The Nimbus Guide](https://nimbus.guide/trusted-node-sync.html) for more information. | ||
|
||
When configured, on first startup, Nimbus will download the checkpoint from the configured URL. Subsequent startups will skip this step. | ||
|
||
**Note:** Always verify after after a checkpoint sync that the right chain was provided by the node. Instructions to do so are included in the above Nimbus Guide link. | ||
|
||
## Using a Nimbus Beacon fork | ||
|
||
A different version of Nimbus Beacon can be configured via the [package](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnamepackage) option. | ||
|
||
To configure a custom fork for example: | ||
|
||
```nix title="server.nix" | ||
{ pkgs, ...}: { | ||
services.ethereum.nimbus-beacon.sepolia = { | ||
enable = true; | ||
package = pkgs.my-nimbus-beacon; | ||
... | ||
}; | ||
} | ||
``` | ||
|
||
## Opening ports | ||
|
||
By default, [openFirewall](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameopenfirewall) is set to `false`. | ||
If set to `true` firewall rules are added which will expose the following ports: | ||
|
||
| Protocol | Config | Default value | | ||
| :------- | :------------------------------------------------------------------------------------------------------- | :------------ | | ||
| TCP | [tcp-port](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameargstcp-port) | 9000 | | ||
| UDP | [udp-port](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameargsudp-port) | 9000 | | ||
| TCP | [rest-port](./modules/nimbus-beacon.md#servicesethereumnimbus-beaconnameargsrest-port) | 5052 | | ||
|
||
**Note:** it is important when running multiple instances of Nimbus Beacon on the same machine that you ensure they are configured with different ports. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
{ | ||
lib, | ||
name, | ||
... | ||
}: | ||
with lib; { | ||
network = mkOption { | ||
type = types.enum ["mainnet" "prater" "sepolia" "holesky"]; | ||
default = name; | ||
defaultText = "name"; | ||
description = mdDoc "The Eth2 network to join"; | ||
}; | ||
|
||
el = mkOption { | ||
type = types.listOf types.str; | ||
default = ["http://127.0.0.1:8551"]; | ||
description = lib.mdDoc '' | ||
One or more Execution Layer Engine API URLs. | ||
''; | ||
}; | ||
|
||
listen-address = mkOption { | ||
type = types.str; | ||
default = "0.0.0.0"; | ||
description = lib.mdDoc '' | ||
Listening address for the Ethereum LibP2P and Discovery v5 traffic | ||
''; | ||
}; | ||
|
||
tcp-port = mkOption { | ||
type = types.port; | ||
default = 9000; | ||
description = mdDoc "The port used for LibP2P traffic."; | ||
}; | ||
|
||
udp-port = mkOption { | ||
type = types.port; | ||
default = 9000; | ||
description = mdDoc "The port used for node discovery."; | ||
}; | ||
|
||
nat = mkOption { | ||
type = types.str; | ||
default = "any"; | ||
description = mdDoc "Specify method to use for determining public address. Must be one of: any, none, upnp, pmp, extip:<IP>"; | ||
}; | ||
|
||
enr-auto-update = mkOption { | ||
type = types.bool; | ||
default = false; | ||
description = mdDoc "Discovery can automatically update its ENR with the IP address and UDP port as seen by other nodes it communicates with. This option allows to enable/disable this functionality."; | ||
}; | ||
|
||
jwt-secret = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc '' | ||
A file containing the hex-encoded 256 bit secret key to be used for verifying/generating JWT tokens. | ||
''; | ||
example = "/var/run/nimbus/jwtsecret"; | ||
}; | ||
|
||
trusted-node-url = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc '' | ||
URL of a synced beacon node to trust in obtaining checkpoint sync data. | ||
''; | ||
example = "https://checkpoint-sync.goerli.ethpandaops.io"; | ||
}; | ||
|
||
max-peers = mkOption { | ||
type = types.str; | ||
default = "160"; | ||
description = mdDoc "The target number of peers to connect to"; | ||
}; | ||
|
||
doppelganger-detection = mkOption { | ||
type = types.bool; | ||
default = true; | ||
description = mdDoc "If enabled, the beacon node prudently listens for 2 epochs for attestations from a validator with the same index (a doppelganger), before sending an attestation itself. This protects against slashing (due to double-voting) but means you will miss two attestations when restarting."; | ||
}; | ||
|
||
history = mkOption { | ||
type = types.nullOr (types.enum ["archive" "prune"]); | ||
default = "prune"; | ||
description = mdDoc "Retention strategy for historical data"; | ||
}; | ||
|
||
graffiti = mkOption { | ||
type = types.str; | ||
default = ""; | ||
description = mdDoc "The graffiti value that will appear in proposed blocks. You can use a 0x-prefixed hex encoded string to specify raw bytes."; | ||
}; | ||
|
||
metrics = { | ||
enable = mkOption { | ||
type = types.bool; | ||
default = true; | ||
description = mdDoc "Enable Prometheus metrics exporter."; | ||
}; | ||
|
||
address = mkOption { | ||
type = types.str; | ||
default = "127.0.0.1"; | ||
description = mdDoc "Host used to listen and respond with metrics for prometheus."; | ||
}; | ||
|
||
port = mkOption { | ||
type = types.port; | ||
default = 5054; | ||
description = mdDoc "Port used to listen and respond with metrics for prometheus."; | ||
}; | ||
}; | ||
|
||
rest = { | ||
enable = mkOption { | ||
type = types.bool; | ||
default = false; | ||
description = mdDoc "Enable the REST server"; | ||
}; | ||
|
||
address = mkOption { | ||
type = types.str; | ||
default = "127.0.0.1"; | ||
description = mdDoc "Listening address of the REST server"; | ||
}; | ||
|
||
port = mkOption { | ||
type = types.port; | ||
default = 5052; | ||
description = mdDoc "Port for the REST server"; | ||
}; | ||
|
||
allow-origin = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc "Limit the access to the REST API to a particular hostname (for CORS-enabled clients such as browsers)."; | ||
}; | ||
}; | ||
|
||
payload-builder = { | ||
enable = mkOption { | ||
type = types.bool; | ||
default = false; | ||
description = mdDoc "Enable external payload builder "; | ||
}; | ||
url = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc "Payload builder URL."; | ||
}; | ||
}; | ||
light-client-data = { | ||
serve = mkOption { | ||
type = types.bool; | ||
default = true; | ||
description = mdDoc "Whether to serve data for enabling light clients to stay in sync with the network."; | ||
}; | ||
import-mode = mkOption { | ||
type = types.enum ["none" "only-new" "full" "on-demand"]; | ||
default = "only-new"; | ||
description = mdDoc "Which classes of light client data to import. Must be one of: none, only-new, full (slow startup), on-demand (may miss validator duties)."; | ||
}; | ||
max-periods = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc "Maximum number of sync committee periods to retain light client data."; | ||
}; | ||
}; | ||
|
||
data-dir = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc "Data directory for the Nimbus databases. Defaults to '%S/nimbus-beacon-\<name\>', which generally resolves to /var/lib/nimbus-beacon-\<name\>."; | ||
}; | ||
|
||
user = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
description = mdDoc "User to run the systemd service."; | ||
}; | ||
} |
Oops, something went wrong.