Running a Node

How to run an Ethscriptions AppChain node with Docker Compose

This guide explains how to run your own Ethscriptions AppChain node using Docker Compose.

Prerequisites

  • Docker Desktop (includes the Compose plugin)

  • L1 RPC endpoint - Archive-quality recommended for historical sync

Quick Start

# Clone the repository
git clone https://github.com/ethscriptions-protocol/ethscriptions-node.git
cd ethscriptions-node

# Copy the environment template
cp docker-compose/.env.example docker-compose/.env

# Edit .env with your settings (see Environment Reference below)
# At minimum, set L1_RPC_URL to your L1 endpoint

# Bring up the stack
cd docker-compose
docker compose --env-file .env up -d

# Follow logs while it syncs
docker compose logs -f node

# Query the L2 RPC (default port 8545)
curl -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# Shut down when done
docker compose down

Services

The stack runs two containers:

Service
Description

geth

Ethscriptions-customized Ethereum execution client (L2)

node

Ruby derivation app that processes L1 data into L2 blocks

The node waits for geth to be healthy before starting. Both services communicate via a shared IPC socket.

Environment Reference

Key variables in docker-compose/.env:

Core Configuration

Variable
Description
Default

COMPOSE_PROJECT_NAME

Docker resource naming prefix

ethscriptions-evm

JWT_SECRET

32-byte hex for Engine API auth (must match geth)

—

L1_NETWORK

Ethereum network (mainnet, sepolia, etc.)

mainnet

L1_RPC_URL

Archive-quality L1 RPC endpoint

—

L1_GENESIS_BLOCK

L1 block where the rollup anchors

17478949

GENESIS_FILE

Genesis snapshot filename

ethscriptions-mainnet.json

GETH_EXTERNAL_PORT

Host port for L2 RPC

8545

Performance Tuning

Variable
Description
Default

L1_PREFETCH_FORWARD

Blocks to prefetch ahead

200

L1_PREFETCH_THREADS

Prefetch worker threads

10

JOB_CONCURRENCY

SolidQueue worker concurrency

6

JOB_THREADS

Job worker threads

3

Geth Configuration

Variable
Description
Default

GC_MODE

full (pruned) or archive (full history)

full

STATE_HISTORY

State trie history depth

100000

TX_HISTORY

Transaction history depth

100000

ENABLE_PREIMAGES

Retain preimages

true

CACHE_SIZE

State cache size

25000

Validation (Optional)

Variable
Description
Default

VALIDATION_ENABLED

Enable validator against reference API

false

ETHSCRIPTIONS_API_BASE_URL

Reference API endpoint

—

ETHSCRIPTIONS_API_KEY

API authentication key

—

Monitoring

View Logs

Check Block Height

Check Sync Status

The derivation node logs show the current L1 block being processed. Compare this to the current L1 head to gauge sync progress.

Validator (Optional)

The validator compares L2 state against a reference Ethscriptions API to verify derivation correctness. It pauses the importer when discrepancies appear so you can investigate.

To enable:

The temporary SQLite databases in storage/ and the SolidQueue worker pool support this reconciliation. Once historical import is verified, the derivation app remains stateless.

Local Development

If you want to modify the Ruby code outside of Docker:

The Docker Compose stack is recommended for production-like runs.

Troubleshooting

Node won't start

  • Check that geth is healthy: docker compose ps

  • Verify L1_RPC_URL is accessible

  • Ensure JWT_SECRET matches between services

Slow sync

  • Increase L1_PREFETCH_FORWARD and L1_PREFETCH_THREADS

  • Use a faster L1 RPC endpoint

  • Consider archive mode (GC_MODE=archive) only if needed

Out of disk space

  • Pruned mode (GC_MODE=full) uses less space

  • Reduce STATE_HISTORY and TX_HISTORY

Resources

Last updated