Run Ethereum multi-client devnets using Kurtosis and the ethpandaops/ethereum-package. Use for spinning up local testnets, validating cross-client interop, testing fork transitions, running assertoor checks, debugging CL/EL client interactions, or verifying new feature implementations across multiple consensus and execution clients.
Run Ethereum consensus/execution client devnets via Kurtosis + ethereum-package.
# Start devnet from config
# Always use --image-download always to ensure external images are up to date
kurtosis run github.com/ethpandaops/ethereum-package \
--enclave <name> \
--args-file network_params.yaml \
--image-download always
# List enclaves
kurtosis enclave ls
# Inspect services
kurtosis enclave inspect <name>
# View logs
kurtosis service logs <enclave> <service-name>
kurtosis service logs <enclave> <service-name> --follow
# Cleanup
kurtosis enclave rm -f <name>
# Or clean all enclaves
kurtosis clean -a
network_params.yaml)See references/config-reference.md for the full config structure.
Key sections:
participants: list of CL+EL client pairs with images, flags, validator countsnetwork_params: fork epochs, slot time, network-level settingsadditional_services: dora (explorer), assertoor (testing), prometheus, grafanaassertoor_params: automated chain health checksport_publisher: expose CL/EL ports to hostWhen testing local Lodestar branches, build a Docker image first:
# Fast build (recommended for iteration)
cd ~/lodestar && docker build -t lodestar:custom -f Dockerfile.dev .
# Production build (slower, for final validation only)
cd ~/lodestar && docker build -t lodestar:custom .
# Then reference in config:
# cl_image: lodestar:custom
Always use Dockerfile.dev for iterative development. It caches dependency layers and rebuilds in seconds vs minutes for the production Dockerfile. Only use the production Dockerfile for final validation or debugging build issues.
Kurtosis names services as: {role}-{index}-{cl_type}-{el_type}
Examples:
cl-1-lodestar-reth — first CL node (Lodestar with Reth EL)el-1-reth-lodestar — corresponding EL nodevc-1-lodestar-reth — validator clientAfter kurtosis enclave inspect <name>, find mapped ports:
# CL beacon API (find actual port from inspect output)
curl http://127.0.0.1:<mapped-port>/eth/v1/node/syncing
# Or use port_publisher for predictable ports:
# port_publisher:
# cl:
# enabled: true
# public_port_start: 33000 # cl-1=33000, cl-2=33005, etc.
# el:
# enabled: true
# public_port_start: 32000
Port publisher assigns sequential ports (step of 5 per service).
Add to config:
additional_services:
- assertoor
assertoor_params:
run_stability_check: true # chain stability, finality, no reorgs
run_block_proposal_check: true # every client pair proposes a block
Check results via the assertoor web UI (port shown in kurtosis enclave inspect).
network_params:
electra_fork_epoch: 0
fulu_fork_epoch: 1 # fork at epoch 1 (slot 32)
seconds_per_slot: 6 # faster for testing