Skip to main content

🖥️ Ethereum RPC Node - Geth + Lighthouse

Node briefing

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.

NetworkEthereum Mainnet / Sepolia
Setup time2-4 hours (+ sync time)
Difficulty🟡 Medium

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
Storage Reality Check

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

IssueImpact
Rate limitsSequencer stalls during high activity
DowntimeYour L2 node stops if provider is down
LatencyRemote RPC adds network delay
CostHigh-volume usage gets expensive
PrivacyProvider 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

Checkpoint Sync URLs

Block Explorers (verify sync)


🎯 Summary

ComponentPortPurpose
Geth HTTP RPC8545Transaction queries, state
Geth WebSocket8546Real-time subscriptions
Geth Auth RPC8551Lighthouse communication
Geth P2P30303Ethereum network
Lighthouse HTTP5052Beacon chain API
Lighthouse P2P9000Consensus 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.

© 2026 TokioStack. All rights reserved.
DMCA.com Protection Status