A private Ethereum testnet running with reth (Execution Layer) and Lighthouse (Consensus Layer + Validator Client), orchestrated with Docker Compose.
- Docker
opensslmake
network/
config.yaml # Beacon chain config (chain parameters, fork settings)
genesis.json # EL genesis file (pre-funded accounts, chain ID, etc.)
genesis.ssz # CL genesis state (generated by make regen)
mnemonics.yaml # Validator mnemonics used to derive keys
jwt.hex # Shared JWT secret between reth and lighthouse (generated by make jwt)
deposit_contract.txt # Deposit contract address
deposit_contract_block.txt # Block number of the deposit contract deployment
deposit_contract_block_hash.txt # Block hash of the deposit contract deployment
bootstrap_nodes.txt # ENR bootstrap nodes list (empty for local testnet)
validator-keys/
validators/ # EIP-2335 keystore directories (one per validator)
secrets/ # Keystore password files (one per validator)
make jwtGenerates ./network/jwt.hex used by reth and lighthouse to authenticate over the Engine API.
make keysGenerates EIP-2335 keystore files directly into ./network/validator-keys/ using eth2-val-tools (via Docker).
make regenThis will:
- Stop any running containers (
docker compose down) - Update
MIN_GENESIS_TIMEinconfig.yamlandtimestampingenesis.jsonto the current UTC time - Regenerate
genesis.sszfrom the updated config
make runStarts reth, lighthouse beacon node, and the validator client. Validators should begin attesting within a few slots.
| Command | Description |
|---|---|
make run |
Start the network |
make regen |
Regenerate genesis with current timestamp (run make clean first for a full reset) |
make clean |
Wipe all chain data without touching genesis or key files |
make keys |
Regenerate validator keystores |
make jwt |
Regenerate the JWT secret |
To fully reset and restart from a new genesis:
make clean && make regen && make runThis log line from reth during init can be safely ignored:
ERROR Head block is not reachable
If validators are not attesting after a few minutes, the most likely cause is a stale genesis time. Run make clean && make regen && make run.
The containers run as your current user (UID:GID). If you see permission errors on /tmp/reth, /tmp/lighthouse, or /tmp/validator, those directories are root-owned from a previous run. Remove them and let make run recreate them:
sudo rm -rf /tmp/reth /tmp/lighthouse /tmp/validator
make run