🖥️ Ethereum RPC Node - Geth + Lighthouse
Ethereum RPC Infrastructure
Run your own Ethereum execution (Geth) and consensus (Lighthouse) clients. Essential for L2 sequencer reliability, reducing dependency on third-party RPC providers, and full blockchain sovereignty.
System checklist
- CPU
- 8 cores / 16 vCPU minimum
- RAM
- 22-32 GB recommended
- Storage
- 1.5-2 TB NVMe SSD (critical!)
- Network
- 25+ Mbps stable connection
- OS
- Ubuntu 22.04+
Launch prerequisites
- Docker and Docker Compose installed
- Understanding of Ethereum architecture
- Long-term storage planning
Key features
- Full control over your L1 infrastructure
- No rate limits or API key dependencies
- Required for reliable L2 sequencer operations
- Supports multiple L2 clients simultaneously
This is the most important consideration. Based on real-world experience:
- Geth data: ~730 GB (and growing)
- Lighthouse data: ~400 GB (and growing)
- Total: ~1.1 TB for Sepolia testnet alone
Mainnet requires even more. Plan for 2+ TB NVMe for comfortable operation.
🎯 Why Self-Hosted RPC?
Third-Party RPC Problems
| Issue | Impact |
|---|---|
| Rate limits | Sequencer stalls during high activity |
| Downtime | Your L2 node stops if provider is down |
| Latency | Remote RPC adds network delay |
| Cost | High-volume usage gets expensive |
| Privacy | Provider sees all your queries |
Self-Hosted Benefits
- No rate limits - Query as much as you need
- Full reliability - You control uptime
- Low latency - Local network or same datacenter
- Privacy - No third party sees your activity
- Multi-client - One node serves multiple L2s
🏗️ Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Your VPS │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Geth │◄────►│ Lighthouse │ │
│ │ (Execution) │ │ (Consensus) │ │
│ │ Port 8545 │ │ Port 5052 │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ └─────────┬───────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Aztec Sequencer │ │
│ │ (or other L2s) │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────┘
- Geth (Execution Layer): Processes transactions, maintains state
- Lighthouse (Consensus Layer): PoS consensus, block finality
- L2 Clients: Connect to both for full L1 access
🛠️ Step 1: Prepare Your Server
Verify Storage
# Check total disk space
df -h /
# Check if NVMe (critical for sync speed)
lsblk -d -o name,rota
# rota=0 means SSD/NVMe, rota=1 means HDD (too slow!)
# Check current usage
du -sh /var/lib/docker
Install Dependencies
# Update system
sudo apt update && sudo apt upgrade -y
# Install essentials
sudo apt install -y curl wget git jq htop iotop nvme-cli
# Install Docker (if not already)
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
Create Directory Structure
# Create data directories
mkdir -p ~/ethereum-node/{geth-data,lighthouse-data}
cd ~/ethereum-node
⚙️ Step 2: Configure Geth (Execution Client)
Create docker-compose.yml
nano docker-compose.yml
services:
geth:
container_name: geth
image: ethereum/client-go:stable
restart: unless-stopped
ports:
- "8545:8545" # HTTP RPC
- "8546:8546" # WebSocket
- "30303:30303" # P2P TCP
- "30303:30303/udp" # P2P UDP
volumes:
- ./geth-data:/root/.ethereum
command:
- --http
- --http.addr=0.0.0.0
- --http.port=8545
- --http.api=eth,net,web3,engine,admin
- --http.vhosts=*
- --http.corsdomain=*
- --ws
- --ws.addr=0.0.0.0
- --ws.port=8546
- --ws.api=eth,net,web3,engine
- --authrpc.addr=0.0.0.0
- --authrpc.port=8551
- --authrpc.vhosts=*
- --authrpc.jwtsecret=/root/.ethereum/jwt.hex
- --syncmode=snap
- --cache=4096
# For Sepolia testnet, add:
# - --sepolia
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
lighthouse:
container_name: lighthouse
image: sigp/lighthouse:latest
restart: unless-stopped
depends_on:
- geth
ports:
- "5052:5052" # HTTP API
- "9000:9000" # P2P TCP
- "9000:9000/udp" # P2P UDP
volumes:
- ./lighthouse-data:/root/.lighthouse
- ./geth-data:/geth-data:ro
command:
- lighthouse
- bn
- --network=mainnet
- --execution-endpoint=http://geth:8551
- --execution-jwt=/geth-data/jwt.hex
- --http
- --http-address=0.0.0.0
- --http-port=5052
- --checkpoint-sync-url=https://mainnet.checkpoint.sigp.io
# For Sepolia, change:
# - --network=sepolia
# - --checkpoint-sync-url=https://sepolia.beaconstate.info
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
Generate JWT Secret
# Generate shared secret for Geth-Lighthouse communication
openssl rand -hex 32 > ./geth-data/jwt.hex
chmod 644 ./geth-data/jwt.hex
🚀 Step 3: Start the Nodes
# Start both clients
docker compose up -d
# Check containers are running
docker ps
# View Geth logs
docker logs geth --tail 50 -f
# View Lighthouse logs (in another terminal)
docker logs lighthouse --tail 50 -f
Initial Sync
This takes time! Expect:
- Geth: 6-24 hours for snap sync
- Lighthouse: 1-4 hours with checkpoint sync
Monitor progress:
# Geth sync status
curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' \
http://localhost:8545 | jq
# Lighthouse sync status
curl -s http://localhost:5052/eth/v1/node/syncing | jq
📊 Step 4: Verify Everything Works
Test Geth RPC
# Get latest block number
curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://localhost:8545 | jq -r '.result' | xargs printf "%d\n"
# Get chain ID
curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
http://localhost:8545 | jq
Test Lighthouse API
# Node health
curl -s http://localhost:5052/eth/v1/node/health
# Sync status
curl -s http://localhost:5052/eth/v1/node/syncing | jq
# Peer count
curl -s http://localhost:5052/eth/v1/node/peer_count | jq
💾 Step 5: Disk Space Management
This is the most common issue with self-hosted nodes.
Monitor Disk Usage
# Create monitoring script
cat > ~/check-disk.sh << 'EOF'
#!/bin/bash
echo "=== Disk Usage ==="
df -h /
echo ""
echo "=== Geth Data ==="
du -sh ~/ethereum-node/geth-data
echo ""
echo "=== Lighthouse Data ==="
du -sh ~/ethereum-node/lighthouse-data
echo ""
echo "=== Total Ethereum Node ==="
du -sh ~/ethereum-node
EOF
chmod +x ~/check-disk.sh
Solution A: Periodic Lighthouse Reset (Simplest)
Lighthouse can resync from checkpoint quickly. Reset every 10-15 days:
# Stop Lighthouse
docker compose stop lighthouse
# Delete Lighthouse data
sudo rm -rf ~/ethereum-node/lighthouse-data/*
# Restart (will checkpoint sync)
docker compose up -d lighthouse
# Monitor sync
docker logs lighthouse -f
Solution B: Geth Pruning (Moderate Savings)
Add these flags to reduce Geth storage:
command:
# ... existing flags ...
- --state.scheme=path
- --history.transactions=0
- --cache.preimages=false
Savings: ~100-200 GB (not dramatic)
Solution C: External Lighthouse (Best for Limited Disk)
Use a public Beacon API instead of local Lighthouse:
# In your L2 config, use:
L1_CONSENSUS_HOST_URLS=https://ethereum-beacon-api.publicnode.com
# Then you can delete local Lighthouse entirely
docker compose stop lighthouse
sudo rm -rf ~/ethereum-node/lighthouse-data
Savings: ~400 GB
Trade-off: Dependency on external service for consensus data
Solution D: Split Across VPS (Production Setup)
For serious operations:
- VPS 1: Geth only (800 GB - 1 TB)
- VPS 2: Lighthouse + L2 clients (500 GB)
- Connect via private network
🔧 Maintenance
Daily Health Check
# Quick status
curl -s http://localhost:8545 -X POST \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' | jq
curl -s http://localhost:5052/eth/v1/node/syncing | jq
Update Clients
# Pull latest images
docker compose pull
# Restart with new versions
docker compose down
docker compose up -d
# Verify
docker images | grep -E "ethereum|lighthouse"
Backup Configuration
# Backup docker-compose and JWT (not the data - too large)
mkdir -p ~/backups/ethereum-node
cp ~/ethereum-node/docker-compose.yml ~/backups/ethereum-node/
cp ~/ethereum-node/geth-data/jwt.hex ~/backups/ethereum-node/
🔌 Connect L2 Clients
Aztec Sequencer
In your Aztec .env:
ETHEREUM_HOSTS=http://YOUR_VPS_IP:8545
L1_CONSENSUS_HOST_URLS=http://YOUR_VPS_IP:5052
Multiple L2s
One Geth+Lighthouse setup can serve multiple L2 clients:
- Aztec Sequencer
- Optimism node
- Arbitrum node
- Any other L2 needing L1 data
⚠️ Security Considerations
Firewall Rules
# Allow only necessary ports
sudo ufw allow ssh
sudo ufw allow 30303/tcp # Geth P2P
sudo ufw allow 30303/udp
sudo ufw allow 9000/tcp # Lighthouse P2P
sudo ufw allow 9000/udp
# RPC ports - restrict to specific IPs or internal only
# sudo ufw allow from YOUR_L2_VPS_IP to any port 8545
# sudo ufw allow from YOUR_L2_VPS_IP to any port 5052
sudo ufw enable
Don't Expose RPC Publicly
If your L2 is on the same machine, use localhost. If on different VPS:
- Use VPN/private network
- Or restrict by IP with firewall
🔗 Useful Resources
Official Documentation
- Geth: https://geth.ethereum.org/docs
- Lighthouse: https://lighthouse-book.sigmaprime.io/
Checkpoint Sync URLs
- Mainnet: https://mainnet.checkpoint.sigp.io
- Sepolia: https://sepolia.beaconstate.info
Block Explorers (verify sync)
- Mainnet: https://etherscan.io
- Sepolia: https://sepolia.etherscan.io
🎯 Summary
| Component | Port | Purpose |
|---|---|---|
| Geth HTTP RPC | 8545 | Transaction queries, state |
| Geth WebSocket | 8546 | Real-time subscriptions |
| Geth Auth RPC | 8551 | Lighthouse communication |
| Geth P2P | 30303 | Ethereum network |
| Lighthouse HTTP | 5052 | Beacon chain API |
| Lighthouse P2P | 9000 | Consensus network |
Your L1 infrastructure is now ready! This provides the foundation for reliable L2 operations. 🖥️
This guide is based on real-world experience running Geth + Lighthouse for Aztec sequencer operations.
