Obol DVT Staking¶
What is Obol DVT solution¶
This guide explains how to set up and run a Distributed Validator Technology cluster using Obol’s Charon middleware on Ethereum on ARM.
Distributed Validator Technology (DVT) allows one/multiple operators to run validator(s) together in several nodes, eliminating single points of failure and improving resilience.
What you get with Obol DVT¶
Running an Obol DVT cluster at home provides resilience against the most common causes of validator downtime:
ISP outage — if each node is on a different internet connection, a single provider going down does not affect the cluster
Power blackout — if nodes are geographically distributed, a local power cut only affects one node, and the cluster continues signing
Maintenance windows — hardware upgrades, OS updates, client version bumps and configuration changes can be applied node by node with zero downtime
Hardware failure — a node dying does not stop the cluster. Replace the hardware, resync, and rejoin
True client diversity — each node can run a different Execution and Consensus client. A critical bug in one client only affects the nodes running it — the rest of the cluster continues signing. This also contributes to Ethereum network resilience by avoiding concentration in any single client implementation
For a deeper understanding of how Charon coordinates the cluster and how the DVT threshold signing protocol works, refer to the Obol documentation:
Cluster types¶
Obol supports two ways to run a Distributed Validator cluster:
DV Alone
A single operator runs all nodes in the cluster across different hardware, locations and ISPs. The operator controls all nodes and holds all key shares. This is the simplest setup and the one covered by the step-by-step guide.
DV as a Group
Multiple independent operators each run one node. No single operator holds the full validator key — each holds only a key share generated during a Distributed Key Generation (DKG) ceremony. A threshold of operators must cooperate to sign duties, removing single-operator custody risk.
For further details refer to the Obol documentation:
https://docs.obol.org/learn/intro/obol-collective
Prerequisites¶
Obol cluster nodes¶
You will need at least 3 nodes for a DV Alone cluster. Each node should meet the following requirements:
Hardware: ARM64 device with 24 GB RAM running Ethereum on ARM (Rock 5B, Orange Pi 5 Plus or NanoPC-T6 recommended)
Storage: 2 TB NVMe SSD minimum (TLC, DRAM cache required)
Full Ethereum node: Execution Layer + Consensus Layer clients fully synced on every node
Network: Port 3610 open for P2P communication (TCP and UDP)
Validator keys (DV Alone only): your existing EIP-2335 keystore files if you are migrating from solo staking
Control nodes¶
You will need 2 control nodes (active + failover) for monitoring and backup staking:
Hardware: ARM64 device with 16 GB RAM minimum running Ethereum on ARM
Storage: 2 TB NVMe SSD minimum
Full Ethereum node: Execution Layer + Consensus Layer clients fully synced on every node
Network: VPN connectivity to all Obol cluster nodes
Node naming¶
When setting up each node, choose a hostname that identifies its location, device and
ISP. This makes it easy to trace alerts back to a specific machine and network.
For example: rock5b-plus-home-vodafone, rock5b-plus-office-digi.
The hostname is set during the Ethereum on ARM initial configuration and is used throughout the monitoring alerts.
Telegram notifications¶
The monitoring solution sends alerts via Telegram. You need a Telegram bot and a channel or group to receive messages.
Create a Telegram bot:
Open Telegram and search for
@BotFatherSend
/newbotand follow the prompts to name your botCopy the API token provided — you will need it during installation
Create a Telegram channel or group:
Create a new Telegram group or channel
Add your bot as an administrator
Send any message in the group
Visit the following URL in your browser (replace
<YOUR_TOKEN>with your bot token):https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
Copy the
idvalue from thechatobject in the response — this is yourchat_id. Note that group and channel IDs are negative numbers (e.g.-1001234567890). Copy the full number including the minus sign.
VPN setup¶
A VPN is strongly recommended to reduce network latency between nodes, simplify firewall rules, and allow the control nodes to reach the cluster nodes over a private network. Tailscale is the easiest option — it requires no manual port forwarding and works across different ISPs and locations.
Install Tailscale on all nodes (cluster and control) following the official guide at https://tailscale.com/download, then note down the Tailscale IP assigned to each node.
Package installation¶
Once all nodes are prepared, install the required packages on each node:
sudo apt-get update && sudo apt-get install dvt-obol ethereumonarm-staking-stack
Creating a cluster Alone¶
A solo DVT cluster means a single operator runs all nodes. This section covers two scenarios: migrating existing validators into a DVT cluster, and creating a fresh cluster with new validators.
Case 1: Migrating existing validators¶
If you are already running validators, you need to split your existing keystores across the cluster nodes using Charon’s key splitting feature.
Step 1: Prepare the keystores
Charon’s --split-existing-keys option expects keystores named
keystore-N.json with a matching keystore-N.txt file containing the
password for each keystore. Use the preparation script included with the
ethereumonarm-staking-stack package to rename and prepare your files:
bash /usr/share/ethereumonarm-staking-stack/tools/prepare-validator-keys.sh
The script will ask for the keystores directory (default
/home/ethereum/validator_keys) and the keystore password. It renames all
existing keystore JSON files to the required format and creates the matching
password files.
Step 2: Create the cluster and split the keys
You can run this command on any machine that has the charon binary
installed — your desktop, a laptop, or one of the cluster nodes. It does not
need to be run on a node that will participate in the cluster.
Once the keystores are prepared, use charon create cluster to split them
across the cluster nodes. Replace the values in angle brackets with your own:
charon create cluster \
--nodes=3 \
--network=mainnet \
--name="My Obol Cluster" \
--cluster-dir=/home/ethereum/cluster \
--split-existing-keys \
--split-keys-dir=/home/ethereum/validator_keys \
--fee-recipient-addresses=<0xYOUR_FEE_RECIPIENT> \
--withdrawal-addresses=<0xYOUR_WITHDRAWAL_ADDRESS>
Adjust --nodes to match the number of nodes in your cluster (minimum 3 for
a DV Alone setup).
Warning
Back up the entire --cluster-dir output directory before proceeding.
This directory contains the charon-enr-private-key for each node, the
cluster-lock.json, and the split validator key shares. This data
cannot be regenerated. If it is lost, access to the validators may be
permanently lost. Store copies in at least two separate secure locations.
Step 3: Distribute the node directories
After the command completes, the --cluster-dir will contain one directory
per node (node0, node1, node2, etc.). Copy each directory to its
corresponding node and rename it to /home/ethereum/.charon:
# On the machine where you ran charon create cluster:
scp -r /home/ethereum/cluster/node0/ ethereum@<node1-ip>:/home/ethereum/.charon
scp -r /home/ethereum/cluster/node1/ ethereum@<node2-ip>:/home/ethereum/.charon
scp -r /home/ethereum/cluster/node2/ ethereum@<node3-ip>:/home/ethereum/.charon
Warning
The charon-enr-private-key file inside each node directory is unique to
that node. Never copy the same node directory to multiple machines.
Step 4: Import the validator keys into the validator client
Each node’s split keystores are located at
/home/ethereum/.charon/validator_keys. Use the import scripts included with
the ethereumonarm-staking-stack package to import them into your validator
client. The scripts stop the service, import the keystores one by one using
the matching per-keystore password files, and restart the service automatically.
All scripts default to /home/ethereum/.charon/validator_keys as the source
directory and use a dedicated data directory for the Obol validator instance
to keep it separate from any existing solo staking setup.
Lighthouse — imports into /home/ethereum/.lighthouse-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-lighthouse.sh
Nimbus — imports into /home/ethereum/.nimbus-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-nimbus.sh
Prysm — imports into /home/ethereum/.prysm-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-prysm.sh
Teku — imports into /home/ethereum/.teku-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-teku.sh
Lodestar — imports into /home/ethereum/.lodestar-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-lodestar.sh
Grandine — copies keystores to /home/ethereum/.grandine-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-grandine.sh
Case 2: Creating a fresh cluster with new validators¶
If you do not have existing validators, you need to generate new validator keys as part of the cluster creation process. Charon handles this internally — no separate key generation step is needed.
Step 1: Generate the ENR for each node
On each node that will be part of the cluster, generate a Charon ENR (a cryptographic identity used for peer discovery and authentication):
charon create enr
This creates the file /home/ethereum/.charon/charon-enr-private-key and
prints your ENR to the terminal. It will look like:
enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7...
Warning
Back up /home/ethereum/.charon/charon-enr-private-key securely on each
node. If you lose this file you will not be able to participate in the
cluster.
Collect the ENR output from all nodes before proceeding to the next step.
Step 2: Create the cluster
As with Case 1, this command can be run on any machine with the charon
binary — it does not need to be one of the cluster nodes.
charon create cluster \
--nodes=3 \
--network=mainnet \
--name="My Obol Cluster" \
--cluster-dir=/home/ethereum/cluster \
--fee-recipient-addresses=<0xYOUR_FEE_RECIPIENT> \
--withdrawal-addresses=<0xYOUR_WITHDRAWAL_ADDRESS> \
--operator-enrs=<enr-node1>,<enr-node2>,<enr-node3>
Replace <enr-node1>, <enr-node2>, <enr-node3> with the ENRs
collected in Step 1.
Warning
Back up the entire --cluster-dir output directory before proceeding.
This directory contains the charon-enr-private-key for each node, the
cluster-lock.json, and the generated validator key shares. This data
cannot be regenerated. If it is lost, access to the validators may be
permanently lost. Store copies in at least two separate secure locations.
Step 3: Distribute node directories and import keys
Follow Steps 3 and 4 from Case 1 above to distribute the node directories to each cluster node and import the generated keystores into the validator clients.
Note
The Obol Launchpad at https://launchpad.obol.org provides a web interface for creating clusters, sharing ENRs between operators, and coordinating the DKG ceremony. It is particularly useful for group clusters where operators are geographically distributed. For a DV Alone setup the command-line approach above is simpler and does not require the Launchpad.
Creating a cluster as a Group¶
A group DVT cluster involves multiple independent operators, each running one node. The validator key is never held by any single operator — it is generated jointly during a Distributed Key Generation (DKG) ceremony where each operator receives only a key share.
This process uses the Obol DV Launchpad to coordinate the cluster
configuration and the DKG ceremony between all operators. Unlike a DV Alone
cluster, there is no --split-existing-keys option — new validator keys are
always generated fresh during the ceremony.
The process has two roles:
Creator — configures the cluster parameters and sends invitations to all operators. This role holds no special privilege in the running cluster, it only sets the initial terms that all operators agree to.
Operator — accepts the invitation, contributes their ENR to the ceremony, and runs a node in the cluster.
In a group cluster each operator follows these steps on their own node.
Step 1: Generate your ENR¶
Each operator must generate a Charon ENR (a cryptographic identity used for peer discovery and authentication during the DKG ceremony). Run this on the node that will participate in the cluster:
charon create enr
This creates /home/ethereum/.charon/charon-enr-private-key and prints your
ENR to the terminal:
Created ENR private key: /home/ethereum/.charon/charon-enr-private-key
enr:-JG4QGQpV4qYe32QFUAbY1UyGNtNcrVMip83cvJRhw1brMslPeyELIz3q6dsZ7...
Warning
Back up /home/ethereum/.charon/charon-enr-private-key immediately and
store it in a safe place. If you lose this file you will not be able to
participate in the DKG ceremony or start the cluster.
Share your ENR with the cluster creator. They will need the ENR from every operator before they can configure the cluster on the Launchpad.
Step 2: Creator — configure the cluster on the Launchpad¶
Note
Skip this step if you are joining as an operator and someone else is the creator.
Before starting, the creator must collect from all operators:
Their Ethereum address (used to sign the cluster configuration via MetaMask)
Their ENR (generated in Step 1)
Then:
Go to the DV Launchpad at https://launchpad.obol.org
Connect your wallet (MetaMask or compatible)
Select Create a Cluster with a group then Get Started
Accept the advisories
Enter the Cluster Name and Cluster Size (number of operators). The signing threshold updates automatically
Enter the Ethereum address of each operator. Click Use My Address for your own entry
Select the number of validators (32 ETH each)
Enter your own ENR in the field provided
Choose a withdrawal configuration:
Custom: enter a principal address (receives the 32 ETH + consensus rewards on exit) and a fee recipient address (receives execution layer rewards). Both can be the same address
Split only rewards: uses an Obol Validator Manager contract to split rewards between a principal address and a splitter. Recommended for groups sharing rewards
Split Everything: both principal and rewards are distributed via splitter contracts
Lido CSM: for Lido Community Staking Module clusters
Click Create Cluster Configuration, review all details, then click Confirm and Sign. You will sign up to three transactions:
The
config_hash— a hash of the cluster configurationThe
operator_config_hash— your acceptance of the operator termsYour
ENR— authorising your private key to act in the cluster
Share the cluster invite link with all operators
Step 3: Operators — accept the invitation and sign¶
Each operator (including the creator if they are also an operator):
Open the invite link shared by the creator
Connect your wallet
Review the cluster configuration
Enter your ENR generated in Step 1
Sign the configuration with your wallet
Once all operators have signed, the Launchpad shows everyone as ready and the DKG ceremony can begin.
Step 4: Run the DKG ceremony¶
All operators must run the DKG ceremony at the same time. Coordinate with all other operators before starting — the ceremony requires all nodes to be online simultaneously.
On each node, run:
charon dkg --definition-file=<URL_OR_PATH_TO_CLUSTER_DEFINITION>
The --definition-file value is either:
The cluster definition URL from the Launchpad invite link (starts with
https://api.obol.tech/dv/...), orA local path to the
cluster-definition.jsonfile if distributed manually
Example with a Launchpad URL:
charon dkg \
--definition-file="https://api.obol.tech/dv/0x..." \
--data-dir=/home/ethereum/.charon
The ceremony takes a few minutes. When it completes successfully, each node
will have its own key share and a cluster-lock.json file written to
/home/ethereum/.charon/. The output looks like:
Successfully completed DKG ceremony
Created /home/ethereum/.charon/cluster-lock.json
Created /home/ethereum/.charon/validator_keys/keystore-0.json
Warning
Back up the entire /home/ethereum/.charon/ directory immediately after
the ceremony. This contains your key share, the cluster lock, and the
charon-enr-private-key. This data cannot be regenerated. If it is
lost you will permanently lose access to your key share.
Step 5: Import the validator keys¶
After the DKG ceremony each operator imports their key share into their
validator client. Use the import scripts included with the
ethereumonarm-staking-stack package. All scripts read from
/home/ethereum/.charon/validator_keys by default.
Lighthouse — imports into /home/ethereum/.lighthouse-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-lighthouse.sh
Nimbus — imports into /home/ethereum/.nimbus-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-nimbus.sh
Prysm — imports into /home/ethereum/.prysm-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-prysm.sh
Teku — imports into /home/ethereum/.teku-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-teku.sh
Lodestar — imports into /home/ethereum/.lodestar-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-lodestar.sh
Grandine — copies keystores to /home/ethereum/.grandine-validator-obol:
bash /usr/share/ethereumonarm-staking-stack/tools/import-validators-grandine.sh
Note
For the validator duties monitor on the control node, copy
cluster-lock.json from any operator node to the control node and provide
its path during the ethereumonarm-staking-stack installation. The monitor
uses the full validator public keys from cluster-lock.json to track
duties on the beacon chain.
Monitoring the Obol cluster¶
The ethereumonarm-staking-stack package includes a comprehensive monitoring
solution that sends Telegram alerts for cluster health, validator duties, node
connectivity, and client updates. Alerts are sent to the Telegram channel or
group created in the Telegram notifications section of the prerequisites.
The monitoring covers three node roles, each installed separately.
Obol node¶
Install on each of the 3 Obol cluster nodes. The Obol node monitor checks its own services, sync status, Charon DVT connectivity, peer counts, and system resources (disk, swap, CPU temperature). It sends alerts directly to Telegram and does not depend on the control nodes.
Run the installer on each Obol node:
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh obol
The installer will ask for:
Node name — a label used in all alert messages (e.g.
rock5b-plus-home-vodafone)Telegram bot token — from
@BotFather(see Prerequisites)Telegram chat ID — the
idfromgetUpdates(see Prerequisites)VPN IP — the Tailscale (or other VPN) IP of this node (optional but recommended)
Cluster size — number of nodes in the cluster (e.g.
3)Lido CSM — whether this cluster is running Lido Community Staking Module validators
Once installed, test the scripts manually before enabling the crontab:
sudo -u ethereum bash /usr/share/ethereumonarm-staking-stack/obol-monitor/scripts/obol-health.sh
Then install the crontab to start automated monitoring:
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh obol crontab
Active control node¶
Install on the active control node. The control node monitor checks all Obol nodes remotely every 5 minutes via Charon’s HTTP API, monitors the failover control node, runs the validator duties checker every 7 minutes, and checks its own local services. All alerts include recovery notifications when conditions resolve.
Before running the installer, ensure the active control node can reach all Obol nodes over VPN (Tailscale or equivalent).
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh control
The installer will ask for:
Node name — label for this control node in alerts
Telegram bot token and chat ID — same as the Obol nodes
Cluster size — number of Obol nodes being monitored
VPN IP of each Obol node — used to query Charon’s API on port 3620
Failover control node VPN IP — the active node monitors the failover and alerts if it goes down
Keystore or cluster-lock directory — for validator duties monitoring:
DV Alone: path to the directory containing EIP-2335 keystore files (default
/home/ethereum/validator_keys)DV as a Group: path to
cluster-lock.jsoncopied from an Obol node (e.g./home/ethereum/cluster-lock.json). The full validator public keys are read from this file automatically
Test before enabling crontab:
sudo -u ethereum bash /usr/share/ethereumonarm-staking-stack/obol-monitor/scripts/control-health.sh
sudo -u ethereum bash /usr/share/ethereumonarm-staking-stack/obol-monitor/scripts/validator-duties.sh
Install the crontab:
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh control crontab
Failover control node¶
Install on the failover control node. The failover node is passive by default — it probes the active control node every 5 minutes and takes over monitoring automatically if the active node becomes unreachable. It runs the same validator duties checks but defers to the active node while it is online, preventing duplicate alerts.
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh control-failover
The installer will ask for the same information as the active control node, plus:
Active control node VPN IP — used to probe the primary node and decide when to take over
The failover probes the active node using three checks in sequence:
EL API query — if the primary responds, the failover defers silently
Charon relay query — if the relay responds but EL does not, the node is up and the failover still defers
VPN ping — only reached if both EL and relay fail. If the ping also fails across two consecutive check cycles, the failover takes over
All peer-related alerts require two consecutive failing cycles (~10 minutes) before firing. This prevents false alerts caused by transient VPN re-keying or brief service restarts.
Test before enabling crontab:
sudo -u ethereum bash /usr/share/ethereumonarm-staking-stack/obol-monitor/scripts/control-health.sh
Install the crontab:
bash /usr/share/ethereumonarm-staking-stack/obol-monitor/install.sh control-failover crontab
Note
If the control node’s VPN connection drops, all Obol nodes will appear
unreachable even if the cluster is healthy. The monitor detects this
condition by pinging the Obol nodes before running remote checks — if none
respond, a single ⚠️ Network connectivity lost alert is sent instead of
a cascade of false node-down alerts. Remote checks are suspended until
connectivity is restored.
Alerts and recovery notifications¶
All alerts include automatic recovery notifications — when a condition
resolves, a ✅ message is sent to Telegram without any additional
configuration. Alert deduplication prevents repeated messages for the same
condition using per-condition lock files. Standard alerts do not repeat for
24 hours. Failover and peer-down alerts use a 72-hour window to ensure
recovery messages are not missed.
A full cluster status report is sent every Monday at 08:00 and is also
triggered automatically on incident start and recovery. The daily package
update check (09:00) sends a 📦 alert whenever a new version of a running
client (EL, CL, MEV-Boost or Charon) is available in the Ethereum on ARM APT
repository.