Skip to content

Commit

Permalink
feat: implement Nimbus beacon service (#434)
Browse files Browse the repository at this point in the history
Implement Nimbus Beacon service
  • Loading branch information
iofq authored Feb 2, 2024
1 parent b85be0f commit 0ccb71b
Show file tree
Hide file tree
Showing 6 changed files with 510 additions and 0 deletions.
86 changes: 86 additions & 0 deletions docs/nixos/running-nimbus-beacon.md
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.
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ nav:
- nixos/running-geth.md
- nixos/running-prysm-beacon.md
- nixos/running-lighthouse-beacon.md
- nixos/running-nimbus-beacon.md
- nixos/backup-and-restore.md
- Module Options:
- nixos/modules/erigon.md
Expand All @@ -95,6 +96,7 @@ nav:
- nixos/modules/prysm-validator.md
- nixos/modules/lighthouse-beacon.md
- nixos/modules/lighthouse-validator.md
- nixos/modules/nimbus-beacon.md
- Contributing:
- Reporting a bug: contributing/reporting-a-bug.md
- Reporting a docs issue: contributing/reporting-a-docs-issue.md
Expand Down
1 change: 1 addition & 0 deletions modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
./lighthouse-validator
./mev-boost
./nethermind
./nimbus-beacon
./prysm-beacon
./prysm-validator
./restore
Expand Down
183 changes: 183 additions & 0 deletions modules/nimbus-beacon/args.nix
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.";
};
}
Loading

0 comments on commit 0ccb71b

Please sign in to comment.