# ethereum-rpc-docker — Blockchain RPC Node Configurations **ethereum-rpc-docker** provides production-ready Docker Compose configurations for running blockchain RPC nodes. Whether you're running a single Ethereum node or a fleet of L2s, this repository has everything you need to get started quickly. For **debugging and troubleshooting**, see [VIBE.md](VIBE.md) — the automated operations guide. --- ## 1. What This Repository Is This is a collection of Docker Compose files and supporting scripts for operating blockchain RPC nodes. Each compose file defines a complete node configuration including: - **Client** (execution layer): Geth, Erigon, Reth, Nethermind, Besu, etc. - **Node** (consensus layer): op-node, lighthouse, prysm, nitro, etc. - **Relay** (data availability): eigenda-proxy, op-alt, celestia, etc. - **Proxy** (access layer): nginx for HTTP/WS unification - **Monitoring**: Prometheus metrics, Grafana dashboards You can run a single node or combine multiple compose files to create a full fleet. --- ## 2. Quick Start ### Prerequisites - Docker and Docker Compose installed - Docker daemon running - Public IP address (for P2P connectivity) - At least 500GB free disk for Ethereum mainnet pruned nodes ### Step 1: Create Your Environment File Create a `.env` file in this directory. Here's a complete example: ```bash # === REQUIRED: Network Settings === # Your public IP address (required for P2P on most chains) IP=203.0.113.42 # Docker internal subnet for chain containers CHAINS_SUBNET=192.168.0.0/26 # === REQUIRED: SSL Settings === # Domain for Traefik SSL certificates (use traefik.me for testing) DOMAIN=203-0-113-42.traefik.me # Email for Let's Encrypt notifications MAIL=your-email@example.com # IP whitelist (CIDR notation, 0.0.0.0/0 allows all) WHITELIST=0.0.0.0/0 # === OPTIONAL: SSL === # Disable SSL for local testing (remove for production) # NO_SSL=true # === OPTIONAL: Fallback RPC Endpoints === # These are used by nodes for initial sync and as fallbacks ETHEREUM_MAINNET_EXECUTION_RPC=https://ethereum-rpc.publicnode.com ETHEREUM_MAINNET_EXECUTION_WS=wss://ethereum-rpc.publicnode.com ETHEREUM_MAINNET_BEACON_REST=https://ethereum-beacon-api.publicnode.com ETHEREUM_SEPOLIA_EXECUTION_RPC=https://ethereum-sepolia-rpc.publicnode.com ETHEREUM_SEPOLIA_EXECUTION_WS=wss://ethereum-sepolia-rpc.publicnode.com ARBITRUM_SEPOLIA_EXECUTION_RPC=https://arbitrum-sepolia-rpc.publicnode.com ``` **To get your public IP:** ```bash curl ipinfo.io/ip ``` **For traefik.me domain:** Replace dots with hyphens in your IP: ```bash IP=203.0.113.42 DOMAIN=203-0-113-42.traefik.me ``` ### Step 2: Select Which Nodes to Run Add compose files to the `COMPOSE_FILE` variable in your `.env`. Always include `base.yml` and `rpc.yml` first, then add your node configurations: ```bash # Example: Run Ethereum mainnet with Geth (pruned) COMPOSE_FILE=base.yml:rpc.yml:ethereum-mainnet-geth-pruned.yml # Example: Run multiple nodes COMPOSE_FILE=base.yml:rpc.yml:ethereum-mainnet-geth-pruned.yml:arbitrum-one.yml:optimism-mainnet.yml # Example: Include monitoring COMPOSE_FILE=base.yml:rpc.yml:monitoring.yml:ethereum-mainnet-geth-pruned.yml ``` ### Step 3: Start Your Nodes ```bash # Start all configured nodes docker compose up -d # Check status of all nodes ./show-status.sh # View logs for a specific node ./logs.sh ethereum-mainnet-geth-pruned ``` ### Step 4: Access Your RPC Endpoints Once your nodes are running, access them at: ``` # HTTPS (via Traefik) https:///ethereum-mainnet-geth-pruned # HTTP (if NO_SSL=true) http:///ethereum-mainnet-geth-pruned # WebSocket wss:///ethereum-mainnet-geth-pruned ``` --- ## 3. Configuration Guide ### Environment Variables Reference #### Required Variables | Variable | Description | Example | |---|---|---| | `IP` | Your public IP address | `203.0.113.42` | | `DOMAIN` | Your domain for SSL | `203-0-113-42.traefik.me` | | `MAIL` | Email for Let's Encrypt | `admin@example.com` | | `COMPOSE_FILE` | Which compose files to load | `base.yml:rpc.yml:ethereum-mainnet.yml` | #### Optional Variables | Variable | Description | Default | |---|---|---| | `WHITELIST` | IP whitelist (CIDR) | `0.0.0.0/0` (all) | | `CHAINS_SUBNET` | Docker network subnet | `192.168.0.0/26` | | `NO_SSL` | Disable SSL | Not set (SSL enabled) | #### Chain-Specific Variables These are automatically used by nodes that support them: | Variable | Description | |---|---| | `ETHEREUM_*_EXECUTION_RPC` | Fallback JSON-RPC endpoint | | `ETHEREUM_*_EXECUTION_WS` | Fallback WebSocket endpoint | | `ETHEREUM_*_BEACON_REST` | Fallback Beacon API endpoint | | `OP_NODE_NETWORK` | OP Stack network identifier | | `OP_NODE_L1_RPC_URL` | L1 RPC endpoint for OP Stack | ### Static Compose Files These files provide infrastructure and should always be included: | File | Purpose | Required? | |---|---|---| | `base.yml` | Base Docker networking | ✅ Yes | | `rpc.yml` | RPC gateway configuration | ✅ Yes | | `monitoring.yml` | Prometheus + Grafana stack | ❌ No | | `prometheus.yml` | Prometheus configuration | ❌ No | | `nodeexporter.yml` | Node metrics exporter | ❌ No | | `cadvisor.yml` | Container metrics | ❌ No | | `drpc.yml` | DRPC gateway | ❌ No | | `drpc-free.yml` | DRPC free tier | ❌ No | | `backup-http.yml` | Backup HTTP server | ❌ No | | `logging-proxy.yml` | Logging infrastructure | ❌ No | | `portainer.yml` | Portainer UI | ❌ No | | `benchmark-proxy.yml` | Latency testing | ❌ No | --- ## 4. Available Networks ### Layer 1 Networks #### Major Networks - **Ethereum**: Mainnet, Sepolia, Holesky - **BSC** (Binance Smart Chain): Mainnet - **Polygon**: Mainnet, Amoy - **Avalanche**: C-Chain Mainnet - **Gnosis**: Mainnet, Chiado #### Alternative L1s - **Fantom**: Mainnet, Testnet - **Core**: Mainnet - **Berachain**: Mainnet, Testnet - **Ronin**: Mainnet - **Viction**: Mainnet - **Fuse**: Mainnet - **Tron**: Mainnet - **ThunderCore**: Mainnet #### Emerging L1s - **Goat**: Mainnet, Testnet - **AlephZero**: Mainnet - **Haqq**: Mainnet, Testnet - **Taiko**: Mainnet - **Rootstock**: Mainnet ### Layer 2 Networks #### OP Stack - Optimism: Mainnet, Sepolia - Base: Mainnet, Sepolia - Zora: Mainnet - Mode: Mainnet - Blast: Mainnet - Fraxtal: Mainnet - Bob: Mainnet - Boba: Mainnet, Testnet - Worldchain: Mainnet - Metal: Mainnet - Ink: Mainnet - Lisk: Mainnet, Sepolia - SNAX: Mainnet - Celo: Mainnet #### Arbitrum Ecosystem - Arbitrum One: Mainnet - Arbitrum Nova: Mainnet - Everclear: Mainnet - Playblock: Mainnet - Real: Mainnet - Connext: Mainnet - OpenCampusCodex: Mainnet #### Other L2s - Linea: Mainnet - Scroll: Mainnet, Sepolia - zkSync Era: Mainnet - Metis: Mainnet - Moonbeam: Mainnet - Starknet: Mainnet - zkEVM: Mainnet - Immutable zkEVM: Mainnet - Polygon zkEVM: Mainnet ### Node Types Available For most networks, you can choose from: | Sync Mode | Database | Client | Use Case | |---|---|---|---| | Pruned | Various | Geth, Erigon, Reth | Standard production | | Archive | Various | Geth, Erigon, Reth | Full history, analytics | | Archive-Trace | Various | Reth, Erigon | Full history + transaction tracing | --- ## 5. Accessing Your Nodes ### URL Patterns Each node is accessible via Traefik reverse proxy at: ``` https:/// ``` Where `` is the compose filename without `.yml`, e.g.: - `ethereum-mainnet-geth-pruned` - `op-base-sepolia-op-reth-pruned-trace` - `arbitrum-one-arbnode-archive` ### Ports | Service | Port | Protocol | Notes | |---|---|---|---| | Traefik HTTP | 80 | TCP | Redirects to HTTPS | | Traefik HTTPS | 443 | TCP | SSL termination | | Docker internal | Various | TCP/UDP | P2P and internal communications | **Note:** P2P ports are randomized to avoid conflicts. Check your compose file for specific port mappings. ### Local Access (Without SSL) For local development/testing, set `NO_SSL=true` in your `.env`: ```bash # Access locally without SSL echo "NO_SSL=true" >> .env docker compose up -d # Then access at: http://localhost: ``` Find the port in your compose file or use: ```bash ./get-local-url.sh ``` --- ## 6. Resource Requirements ### Hardware Recommendations | Node Type | Disk | RAM | CPU | Notes | |---|---|---|---|---| | Ethereum Pruned | 500GB - 1TB | 8GB | 2+ cores | Standard production | | Ethereum Archive | 2TB - 4TB | 16GB+ | 4+ cores | Full history | | Ethereum Archive-Trace | 4TB - 8TB | 32GB+ | 8+ cores | Full + tracing | | BSC Pruned | 500GB - 800GB | 8GB | 2+ cores | | | BSC Archive | 2TB - 3TB | 16GB | 4+ cores | | | Polygon Pruned | 300GB - 500GB | 8GB | 2+ cores | | | Polygon Archive | 1TB - 2TB | 16GB | 4+ cores | | | L2 Pruned (OP Stack) | 100GB - 300GB | 4-8GB | 2+ cores | Base, Optimism, etc. | | L2 Archive (OP Stack) | 500GB - 1TB | 8-16GB | 4+ cores | | | L2 Pruned (Arbitrum) | 200GB - 500GB | 4-8GB | 2+ cores | | | L2 Archive (Arbitrum) | 1TB - 2TB | 8-16GB | 4+ cores | | ### Storage Recommendations - **Use SSD or NVMe**: HDDs are too slow for blockchain nodes - **Separate volumes**: Consider separating chain data from OS - **Monitor usage**: Use `./show-db-size.sh` to track growth - **Plan for growth**: Archive nodes grow ~1-2GB/day for Ethereum ### Performance Tips - **CPU**: More cores = faster sync, but diminishing returns after 8 cores - **RAM**: Archive nodes need sufficient RAM for state - **Disk I/O**: NVMe > SSD > HDD. RAID 0 can help for multiple nodes - **Network**: 1Gbps+ recommended for multiple nodes --- ## 7. SSL Certificates and Domain Setup ### Traefik.me (Testing/Development) For quick testing, use the free traefik.me service: ```bash # Get your IP IP=$(curl -s ipinfo.io/ip) # Create domain by replacing dots with hyphens DOMAIN=$(echo $IP | tr . -).traefik.me # Add to .env echo "DOMAIN=$DOMAIN" >> .env echo "MAIL=your-email@example.com" >> .env ``` Traefik.me automatically provides valid SSL certificates. No additional setup needed. ### Let's Encrypt (Production) For production, use your own domain with Let's Encrypt: ```bash # Set your domain DOMAIN=yourdomain.com # Set your email for notifications MAIL=admin@yourdomain.com # Add to .env echo "DOMAIN=$DOMAIN" >> .env echo "MAIL=$MAIL" >> .env ``` Traefik will automatically obtain and renew certificates from Let's Encrypt. ### Disabling SSL For local development, you can disable SSL: ```bash # In .env echo "NO_SSL=true" >> .env # Then restart docker compose up -d ``` --- ## 8. DRPC Integration — Monetize Your RPC [DRPC](https://drpc.org/) allows you to sell excess RPC capacity and earn revenue. ### Quick Setup 1. **Enable DRPC in your `.env`:** ```bash # Add to .env GW_DOMAIN=your-gateway-domain.com GW_REDIS_RAM=2gb DRPC_VERSION=0.64.16 ``` 2. **Add DRPC to COMPOSE_FILE:** ```bash COMPOSE_FILE=base.yml:rpc.yml:drpc.yml:ethereum-mainnet-geth-pruned.yml ``` 3. **Generate upstreams configuration:** ```bash ./upstreams.sh ``` The `upstreams.sh` script automatically detects all running nodes on your machine and generates the configuration for the dshackle load balancer. ### Configuration Options | Variable | Description | Default | |---|---|---| | `GW_DOMAIN` | Your gateway domain | Required | | `GW_REDIS_RAM` | Redis memory limit | `2gb` | | `DRPC_VERSION` | DRPC version to use | Latest | ### Multi-Server Setup For running DRPC across multiple servers: 1. On each server, run nodes with DRPC enabled 2. On your gateway server, run `./upstreams.sh` to generate combined config 3. Deploy the dshackle configuration to your gateway For more information, visit [drpc.org](https://drpc.org/). --- ## 9. Backup and Restore System ### Why Backups Matter - **Database corruption**: Power loss or bugs can corrupt your chain data - **Quick recovery**: Restore from backup instead of re-syncing from scratch - **Migration**: Move nodes between servers efficiently - **Cloning**: Create identical nodes for redundancy ### Local Backups ```bash # Create a backup of a node ./backup-node.sh ethereum-mainnet-geth-pruned # Backup is stored in /backup directory # List available backups ./list-backups.sh # Restore from latest backup ./restore-volumes.sh ethereum-mainnet-geth-pruned ``` ### Remote Backups (WebDAV) For multi-server setups, use WebDAV for remote backups: ```bash # Backup to remote WebDAV ./backup-node.sh ethereum-mainnet https://backup-server.tld/dav # Restore from remote WebDAV ./restore-volumes.sh ethereum-mainnet https://backup-server.tld/backup/ ``` ### HTTP Backup Server Expose your backups via HTTP for easy access: ```bash # Add to COMPOSE_FILE COMPOSE_FILE=base.yml:rpc.yml:backup-http.yml:ethereum-mainnet.yml # Access backups at: # - HTTP: https://yourdomain.tld/backup # - WebDAV: https://yourdomain.tld/dav ``` ### Cross-Server Transfers Transfer node data between servers without SSH: ```bash # On Server A (source): ./backup-node.sh ethereum-mainnet https://server-a.domain.tld/dav # On Server B (destination): ./restore-volumes.sh ethereum-mainnet https://server-a.domain.tld/backup/ ``` ### Cloning Nodes Clone a running node to create a replica: ```bash # Clone node state ./clone-node.sh ethereum-mainnet-geth-pruned # Clone peer connections (faster sync) ./clone-peers.sh ethereum-mainnet-geth-pruned ``` --- ## 10. Security and Network Configuration ### Firewall Configuration Many chains require specific ports for P2P discovery. Docker will bind to these ports on all interfaces (0.0.0.0). **Critical:** You must configure your firewall to: 1. Allow inbound connections to P2P ports (UDP/TCP) 2. Allow outbound connections from containers 3. Block containers from reaching local networks (security) ### iptables Rules Here's a systemd service and script for managing Docker firewall rules: **`/etc/systemd/system/iptables-firewall.service`:** ```ini [Unit] Description= iptables firewall docker fix After=docker.service [Service] ExecStart=/usr/local/bin/iptables-firewall.sh start RemainAfterExit=true StandardOutput=journal [Install] WantedBy=multi-user.target ``` **`/usr/local/bin/iptables-firewall.sh`:** ```bash #!/bin/bash PATH="/sbin:/usr/sbin:/bin:/usr/bin" # Flush existing rules iptables -F DOCKER-USER # Block local networks from containers # (prevents containers from reaching your LAN) iptables -I DOCKER-USER -s {{ chains_subnet }} -d 192.168.0.0/16 -j REJECT iptables -I DOCKER-USER -s {{ chains_subnet }} -d 172.16.0.0/12 -j REJECT iptables -I DOCKER-USER -s {{ chains_subnet }} -d 10.0.0.0/8 -j REJECT # Allow containers to reach each other iptables -I DOCKER-USER -s {{ chains_subnet }} -d {{ chains_subnet }} -j ACCEPT # Allow specific external networks if needed iptables -I DOCKER-USER -s {{ chains_subnet }} -d 10.13.13.0/24 -j ACCEPT ``` Replace `{{ chains_subnet }}` with your `CHAINS_SUBNET` value (default: `192.168.0.0/26`). ### IP Whitelist Control which IPs can access your RPC endpoints: ```bash # In .env - allow all WHITELIST=0.0.0.0/0 # Allow specific IPs WHITELIST=192.0.2.0/24,203.0.113.0/24 # Update whitelist without restart ./update-whitelist.sh ``` --- ## 11. Daily Operations ### Starting and Stopping Nodes ```bash # Start a specific node ./start.sh ethereum-mainnet-geth-pruned # Stop a specific node ./stop.sh ethereum-mainnet-geth-pruned # Restart a node (keeps volumes) ./force-recreate.sh ethereum-mainnet-geth-pruned ``` ### Monitoring Node Health ```bash # Check all nodes ./show-status.sh # Check specific node ./sync-status.sh ethereum-mainnet-geth-pruned # Get latest block ./latest.sh ethereum-mainnet-geth-pruned # Check disk usage ./show-db-size.sh # Check memory usage ./show-ram.sh ethereum-mainnet-geth-pruned ``` ### Viewing Logs ```bash # View logs for a node ./logs.sh ethereum-mainnet-geth-pruned # View logs with follow ./logs.sh ethereum-mainnet-geth-pruned -f # View all container logs docker compose logs -f ``` ### Checking Peers ```bash # Check peer count for all nodes ./peer-count.sh # Check specific node peers ./peer-count.sh | grep ethereum-mainnet ``` --- ## 12. Node Structure and Naming ### Understanding Node Components A typical node consists of one or more of these components: | Component | Purpose | Example Implementations | |---|---|---| | **Client** | Execution layer (handles transactions) | Geth, Erigon, Reth, Nethermind, Besu | | **Node** | Consensus/derivation layer | op-node, lighthouse, prysm, nitro, beacon-kit | | **Relay** | Data availability | eigenda-proxy, op-alt, celestia | | **Proxy** | HTTP/WS unification | nginx | | **Database** | External database | Postgres | ### Naming Conventions **Config names** (compose filenames) follow this pattern: ``` {network}-{chain}-{client}-{syncmode}-{dbtype}.yml ``` Examples: - `ethereum-mainnet-geth-pruned.yml` — Ethereum mainnet, Geth client, pruned - `op-base-sepolia-op-reth-archive-trace.yml` — Base sepolia, op-reth, archive with tracing - `arb-arbitrum-one-arbnode-archive.yml` — Arbitrum One, arbnode, archive **Short names** (used in URLs and container labels): ``` {network}-{chain}[-{client}][-{syncmode}][-{dbtype}] ``` **Volume names**: ``` __ ``` Example: `ethereum-mainnet-geth-pruned_client_data` ### Defaults - **Default client**: geth (Ethereum), op-geth (OP Stack), arbnode (Arbitrum) - **Default sync mode**: pruned - **Default database**: Depends on client (leveldb, pebble, etc.) - **Default node**: op-node (OP Stack), prysm (Ethereum beacon), etc. --- ## 13. Syncing and Initial Setup ### Sync Modes | Mode | Description | Speed | Storage | |---|---|---|---| | **Snap Sync** | Download recent state, verify | Fast | Medium | | **Fast Sync** | Download blocks, verify headers | Medium | Medium | | **Full Sync** | Verify all blocks from genesis | Slow | Full | | **Archive** | Full sync + keep all state | Slowest | Largest | Most nodes use **snap sync** or **fast sync** by default for pruned nodes. ### Using Checkpoints Some nodes support checkpoint sync for faster startup: ```bash # Check if checkpoint is configured grep checkpoint .yml ``` Checkpoints are typically provided by trusted community members or node operators. ### Snapshots For even faster sync, some nodes support snapshot downloads: ```bash # Check snapshot configuration grep snapshot .yml ``` Snapshots are large files containing the entire chain state at a point in time. ### Initial Sync Time | Network | Pruned | Archive | |---|---|---| | Ethereum Mainnet | 1-3 days | 1-2 weeks | | BSC Mainnet | 1-2 days | 3-5 days | | Polygon Mainnet | 6-12 hours | 1-2 days | | L2 Networks | Minutes - hours | Hours - 1 day | Times vary based on hardware, network connection, and chain state. --- ## 14. Common Issues and Solutions ### Container Won't Start **Symptom:** Container exits immediately or fails to start. **Check:** ```bash ./logs.sh docker ps -a | grep ``` **Common fixes:** - Check `.env` file has all required variables - Validate compose syntax: `docker compose -f .yml config` - Ensure ports aren't conflicting - Pull images: `docker compose pull` ### Not Syncing / Stuck **Symptom:** Node shows 0 peers or stuck at low block. **Check:** ```bash ./sync-status.sh ./peer-count.sh | grep ./logs.sh | grep -i error ``` **Common fixes:** - Set `IP=` in `.env` (required for P2P) - Check firewall allows P2P ports - Verify checkpoint/snapshot URLs are reachable - Restart with fresh volumes ### RPC Endpoint Not Accessible **Symptom:** Can't connect to RPC endpoint. **Check:** ```bash ./show-status.sh curl http://localhost: docker ps | grep traefik ``` **Common fixes:** - Check Traefik is running - Verify DOMAIN is set correctly - Check SSL configuration - Test with NO_SSL=true for debugging ### High Resource Usage **Symptom:** Node using too much CPU, memory, or disk. **Check:** ```bash ./show-ram.sh ./show-db-size.sh ./show-cpu.sh ``` **Common fixes:** - Reduce max peers - Upgrade hardware - Switch to pruned mode - Limit specific resources in compose file ### For More Debugging For detailed debugging workflows, error patterns, and advanced troubleshooting, see [VIBE.md](VIBE.md). --- ## 15. Utility Scripts Overview This repository includes many scripts for managing your nodes. For the complete debugging reference, see [VIBE.md](VIBE.md). ### Most Useful for Daily Operations | Script | What It Does | |---|---| | `show-status.sh` | Show health of all running nodes | | `show-running.sh` | List running containers | | `logs.sh ` | View node logs | | `sync-status.sh ` | Check sync progress | | `latest.sh ` | Get latest block | | `stop.sh ` | Stop a node | | `start.sh ` | Start a node | | `force-recreate.sh ` | Restart a node | | `backup-node.sh ` | Create backup | | `restore-volumes.sh ` | Restore from backup | --- ## 16. Learning More - **[VIBE.md](VIBE.md)** — Complete debugging and operations guide for automated tools - **[DRPC Documentation](https://drpc.org/)** — For monetization setup - **[Traefik Documentation](https://doc.traefik.io/traefik/)** — For SSL and reverse proxy - **[Docker Compose Documentation](https://docs.docker.com/compose/)** — For compose file reference --- *For debugging and troubleshooting, see [VIBE.md](VIBE.md).* *For the complete script reference and advanced operations, see [VIBE.md](VIBE.md).*