DEV Community

iapilgrim
iapilgrim

Posted on

Deploying a Base Sepolia Node with Docker

We're using QuickNode for Base Sepolia. This post is how to setup our own node.

1. Prerequisites

  • Docker & Docker Compose installed.
  • L1 RPC Endpoint: A synced Ethereum Sepolia node (e.g., Geth + Lighthouse).
  • L1 Beacon Endpoint: Required for post-Canyon/Ecotone consensus.
  • Hardware: Minimum 16GB RAM and 1.5TB+ NVMe SSD.

2. The Automated Setup Script

We use a wrapper script to handle directory creation, JWT generation, and repository patching. This ensures your local paths are correctly mapped into the Docker containers.

Save as setup-base-sepolia.sh:

#!/usr/bin/env bash
set -e

echo "🚀 Initializing Base Sepolia Setup..."

BASE_DIR="/node-data/testnet/base-sepolia"
REPO_DIR="/opt/base-node"

# 1. Create directory layout
echo "📁 Creating data directories..."
mkdir -p ${BASE_DIR}/{op-geth,op-node,shared}

# 2. Generate the JWT Secret (The "Handshake" Key)
if [ ! -f "${BASE_DIR}/shared/jwt.txt" ]; then
  echo "🔑 Generating 32-byte hex JWT..."
  # CRITICAL: No 0x prefix, no newlines.
  openssl rand -hex 32 | tr -d "\n" > ${BASE_DIR}/shared/jwt.txt
  chmod 644 ${BASE_DIR}/shared/jwt.txt
fi

# 3. Clone the official Base Node Repo
echo "📦 Cloning base-org/node..."
if [ ! -d "${REPO_DIR}" ]; then
  git clone https://github.com/base-org/node.git ${REPO_DIR}
fi

cd ${REPO_DIR}

# 4. Create .env.sepolia
echo "⚙️ Writing environment configuration..."
cat > .env.sepolia <<EOF
# L1 Endpoints (Replace with your actual L1 IPs)
OP_NODE_L1_ETH_RPC=http://testnet:8585
OP_NODE_L1_BEACON=http://testnet-lighthouse:5052

# L2 Execution & Auth
OP_NODE_L2_ENGINE_RPC=http://execution:8551
OP_NODE_L2_ENGINE_AUTH=jwt
OP_NODE_L2_ENGINE_JWT_SECRET=/shared/jwt.txt

# Network & Sync
OP_NODE_NETWORK=base-sepolia
OP_NODE_SYNC_MODE=snap
EOF

# 5. Patch docker-compose.yml for custom volumes
echo "🛠 Patching docker-compose volumes..."
# Map op-geth and op-node to host paths
sed -i 's|${HOST_DATA_DIR}:/data|/node-data/testnet/base-sepolia/op-geth:/data|g' docker-compose.yml
# Inject the shared JWT volume into both services
sed -i '/volumes:/a \      - /node-data/testnet/base-sepolia/shared:/shared' docker-compose.yml

# 6. Start the stack
echo "🚀 Starting containers..."
docker compose --env-file .env.sepolia up -d
Enter fullscreen mode Exit fullscreen mode

3. Critical Configuration Check

For the node to function, your entrypoint scripts inside the repo must use the correct environment variables.

  • execution-entrypoint: Ensure --authrpc.jwtsecret="$OP_NODE_L2_ENGINE_JWT_SECRET" is set.
  • op-node-entrypoint: Ensure --l2.jwt-secret="$OP_NODE_L2_ENGINE_JWT_SECRET" is set.
  • Networking: Ensure --rpc.addr=0.0.0.0 is set in both to allow external monitoring.

4. Troubleshooting & Mastery 🔍

If your node isn't syncing, check these three layers in order:

Layer 1: The JWT Handshake

If op-node cannot talk to op-geth, you will see 401 Unauthorized.

  • Check: docker exec execution-1 cat /shared/jwt.txt
  • Fix: Ensure the file is exactly 64 characters long. If it contains "true" or a file path instead of hex, your script logic is overwriting the secret.

Layer 2: L1 Connectivity

The op-node derives L2 blocks from L1 data. If L1 is down, L2 stops.

  • Check: docker exec node-1 curl -s http://testnet:8585
  • Fix: Ensure your L1 node is fully synced and reachable on the Docker network.

Layer 3: P2P Peering

In snap sync mode, you need peers to download the state.

  • Check: curl -s -d '{"id":1,"jsonrpc":"2.0","method":"opp2p_peerStats"}' http://localhost:9645 | jq
  • Fix: Ensure ports 30303 (Geth) and 9222 (Node) are open on your firewall.

5. Monitoring Your Progress

The most important command for a node operator is the Sync Status. It tells you exactly where you are in history.

The "Scoreboard" Command:

watch -n 5 'curl -s -X POST -H "Content-Type: application/json" --data "{\"jsonrpc\":\"2.0\",\"method\":\"optimism_syncStatus\",\"params\":[],\"id\":1}" http://localhost:9645 | jq ".result.local_safe_l2.number, .result.local_safe_l2.timestamp"'
Enter fullscreen mode Exit fullscreen mode
  • First Number: Current L2 Block Height.
  • Second Number: Unix Timestamp of that block (compare this to the current time to see how many days/months you are behind).

Summary

  1. Generate a clean JWT.
  2. Align your volumes so both containers see the same /shared/jwt.txt.
  3. Point to a healthy L1 RPC and Beacon node.
  4. Monitor via optimism_syncStatus.

Top comments (0)