Overview
This guide provides step-by-step instructions for spinning up a sequencer node after deploying your L1 smart contracts for your OP Stack chain with op-deployer
.
A sequencer node consists of two core components:
- op-geth: Execution layer that processes transactions and maintains state
- op-node: Consensus layer that orders transactions and creates L2 blocks
The sequencer is responsible for:
- Ordering transactions from users
- Building L2 blocks
- Signing blocks on the P2P network
This guide assumes you have already:
- Successfully deployed L1 contracts using
op-deployer apply
- Generated your
genesis.json
androllup.json
configuration files - Have access to the required private keys for sequencer, batcher, and proposer roles
Prerequisites
Essential requirements after op-deployer deployment
Before spinning up your sequencer, ensure you have completed these steps:
1. Successful L1 contract deployment:
- Deployed L1 contracts using
op-deployer apply
- Generated genesis and rollup configuration files using:
op-deployer inspect genesis --workdir .deployer <L2_CHAIN_ID> > .deployer/genesis.json op-deployer inspect rollup --workdir .deployer <L2_CHAIN_ID> > .deployer/rollup.json
2. Required configuration files:
genesis.json
- L2 genesis file for initializing op-gethrollup.json
- Rollup configuration file for op-node- Access to your deployment
state.json
file from op-deployer
3. Essential addresses and keys:
- Sequencer private key - For signing blocks on the P2P network
- Batcher private key - For submitting transaction batches to L1
- Proposer private key - For submitting state roots to L1
4. L1 network access:
- L1 RPC endpoint (Ethereum, Sepolia, etc.)
- L1 Beacon node endpoint
Software requirements
- Git (for cloning repositories)
- Go 1.21+ (if building from source)
- Docker and Docker Compose (optional but recommended)
- OpenSSL for JWT secret generation
Finding the current stable releases
To ensure you're using the latest compatible versions of OP Stack components, always check the official releases page:
release page (opens in a new tab)
The main components you'll need for sequencer deployment are:
- op-node: Look for the latest
op-node/v*
release - op-geth: Look for the latest
op-geth/v*
release (found at https://github.com/ethereum-optimism/op-geth/releases (opens in a new tab))
Docker images
Pre-built Docker images are available for all releases at:
us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:[VERSION]
us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:[VERSION]
Replace [VERSION]
with the specific version tag from the releases page.
Software installation
For spinning up a sequencer, we recommend building from source as it provides better control, and helps with debugging. A Docker alternative is also provided for development or containerized environments.
Build from source (Recommended for production)
Building from source gives you full control over the binaries and is the preferred approach for this guide.
1. Clone and build op-node
# Clone the optimism monorepo
git clone https://github.com/ethereum-optimism/optimism.git
cd optimism
# Checkout the latest release tag
git checkout op-node/v1.13.2
# Build op-node
cd op-node
make op-node
# Binary will be available at ./bin/op-node
2. Clone and build op-geth
# Clone op-geth repository (in a separate directory)
git clone https://github.com/ethereum-optimism/op-geth.git
cd op-geth
# Checkout the latest release tag
git checkout v1.101503.4
# Build op-geth
make geth
# Binary will be available at ./build/bin/geth
Docker alternative (For containerized environments)
If you prefer containerized deployment, you can use the official Docker images. Note that all subsequent configuration examples will need to be adapted for Docker usage.
Pull the required images
# Pull latest op-node image
docker pull us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.2
# Pull latest op-geth image
docker pull us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101503.4
Docker command equivalents
When following the rest of this guide with Docker, replace the binary commands as follows:
Instead of local binary:
./build/bin/geth [arguments]
Use Docker:
docker run --rm -v $(pwd):/workspace \
us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101503.4 \
[arguments]
Instead of local binary:
./bin/op-node [arguments]
Use Docker:
docker run --rm -v $(pwd):/workspace \
--network host \
us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.2 \
[arguments]
Complete Docker setup guide
If you choose the Docker approach, you'll need to:
- Create a docker-compose.yml for easier management:
version: '3.8'
services:
op-geth:
image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101503.4
volumes:
- ./data/op-geth:/data
- ./genesis.json:/genesis.json
- ./jwt.txt:/jwt.txt
ports:
- "8545:8545"
- "8546:8546"
- "8551:8551"
command: |
--datadir=/data
--http --http.addr=0.0.0.0 --http.port=8545
--ws --ws.addr=0.0.0.0 --ws.port=8546
--authrpc.addr=0.0.0.0 --authrpc.port=8551
--authrpc.jwtsecret=/jwt.txt
# ... other geth flags
op-node:
image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.2
depends_on:
- op-geth
volumes:
- ./rollup.json:/rollup.json
- ./jwt.txt:/jwt.txt
ports:
- "8547:8547"
- "9222:9222"
command: |
--l1=${L1_RPC_URL}
--l2=http://op-geth:8551
--rollup.config=/rollup.json
--sequencer.enabled=true
# ... other op-node flags
-
Adapt all subsequent commands to use
docker-compose
or individualdocker run
commands -
Handle networking - containers need to communicate with each other and external services
Verify installation
Regardless of your chosen method, verify your installation:
For build-from-source:
./bin/op-node --version
./build/bin/geth version
For Docker:
docker run --rm us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.2 --version
docker run --rm us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101503.4 version
Note: The rest of this guide assumes you're using the build-from-source approach. If you chose Docker, refer to the command equivalents above or the Docker setup guide in the collapsible section.
Configuration setup
1. Organize your workspace
After building the binaries, you should have the following directory structure:
~/
├── optimism/ # Optimism monorepo
│ └── op-node/
│ └── bin/
│ └── op-node # Built binary
├── op-geth/ # OP-Geth repository
│ └── build/
│ └── bin/
│ └── geth # Built binary
└── .deployer/ # From op-deployer
├── genesis.json
└── rollup.json
Now create your sequencer working directory. We recommend creating it at the same level for easy path references:
# Create sequencer directory at the root level
mkdir ~/sequencer-node
cd ~/sequencer-node
Alternative: Copy binaries to sequencer directory
If you prefer to keep binaries close to your configuration, you can copy them:
mkdir ~/sequencer-node/bin
cp ~/optimism/op-node/bin/op-node ~/sequencer-node/bin/
cp ~/op-geth/build/bin/geth ~/sequencer-node/bin/
# Then update scripts to use:
# ./bin/geth
# ./bin/op-node
2. Generate JWT secret
# Generate JWT secret in the sequencer directory
openssl rand -hex 32 > jwt.txt
# Set appropriate permissions
chmod 600 jwt.txt
3. Set up directory structure and copy files
# Create data directories
mkdir -p data/op-geth data/op-node scripts
# Copy configuration files from op-deployer
cp ~/.deployer/genesis.json .
cp ~/.deployer/rollup.json .
Your final directory structure should look like:
~/sequencer-node/
├── jwt.txt
├── genesis.json
├── rollup.json
├── data/
│ ├── op-geth/
│ └── op-node/
└── scripts/
├── start-op-geth.sh # (to be created)
└── start-op-node.sh # (to be created)
4. Environment variables
You'll need to gather several pieces of information before creating your configuration. Here's where to get each value:
4.1. Get L1 network access
You need access to the L1 network (Ethereum mainnet or Sepolia testnet) and its beacon node:
L1 RPC URL options:
- Infura: Sign up at infura.io (opens in a new tab), create a project, get your API key
- Alchemy: Sign up at alchemy.com (opens in a new tab), create an app, get your API key
L1 Beacon URL options:
- Public beacon APIs:
https://ethereum-sepolia-beacon-api.publicnode.com
(Sepolia) orhttps://ethereum-beacon-api.publicnode.com
(Mainnet) - Infura beacon:
https://sepolia.infura.io/v3/YOUR_KEY
(if your Infura plan includes beacon access)
4.2. Extract sequencer private key from op-deployer
The sequencer private key is used for signing blocks on the P2P network. Find it in your op-deployer intent file:
# View your intent file to find the sequencer private key
cat ~/.deployer/intent.toml
# Look for a section like:
# [chains.my-chain.roles.sequencer]
# privateKey = "0x..."
Note: For this basic sequencer setup, you only need the sequencer private key.
4.3. Get your public IP address
# Find your public IP address
curl ifconfig.me
# or
curl ipinfo.io/ip
4.4. Choose your ports
The default ports are standard but can be changed if needed:
8545
: op-geth HTTP RPC (standard Ethereum RPC port)8546
: op-geth WebSocket RPC8551
: op-geth Auth RPC (for op-node communication)8547
: op-node RPC9222
: P2P networking (must be open on firewall)
Now create your .env
file with the actual values:
# Create .env file with your actual values
# L1 Configuration - Replace with your actual RPC URLs
L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY
L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com
# Sequencer configuration
SEQUENCER_ENABLED=true
SEQUENCER_STOPPED=false
# Private keys - Only sequencer key needed for this setup
SEQUENCER_PRIVATE_KEY=0xYOUR_ACTUAL_SEQUENCER_PRIVATE_KEY
# P2P configuration - Replace with your actual public IP
P2P_LISTEN_PORT=9222
P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP
# RPC configuration (can customize ports if needed)
OP_NODE_RPC_PORT=8547
OP_GETH_HTTP_PORT=8545
OP_GETH_WS_PORT=8546
OP_GETH_AUTH_PORT=8551
# Data directories
DATA_DIR=./data
JWT_SECRET=./jwt.txt
Important: Replace ALL placeholder values (YOUR_ACTUAL_*
) with your real configuration values!
Sequencer specific configuration
op-geth configuration for sequencer
Create scripts/start-op-geth.sh
:
#!/bin/bash
source .env
# Path to the op-geth binary we built
../op-geth/build/bin/geth \
--datadir=$DATA_DIR/op-geth \
--http \
--http.addr=0.0.0.0 \
--http.port=$OP_GETH_HTTP_PORT \
--http.vhosts="*" \
--http.corsdomain="*" \
--http.api=eth,net,web3,debug,txpool,admin \
--ws \
--ws.addr=0.0.0.0 \
--ws.port=$OP_GETH_WS_PORT \
--ws.origins="*" \
--ws.api=eth,net,web3,debug,txpool,admin \
--authrpc.addr=0.0.0.0 \
--authrpc.port=$OP_GETH_AUTH_PORT \
--authrpc.vhosts="*" \
--authrpc.jwtsecret=$JWT_SECRET \
--syncmode=full \
--gcmode=archive \
--rollup.disabletxpoolgossip=true \
--rollup.sequencerhttp=http://localhost:$OP_NODE_RPC_PORT
op-node configuration for sequencer
Create scripts/start-op-node.sh
:
#!/bin/bash
source .env
# Path to the op-node binary we built
../optimism/op-node/bin/op-node \
--l1=$L1_RPC_URL \
--l1.beacon=$L1_BEACON_URL \
--l2=http://localhost:$OP_GETH_AUTH_PORT \
--l2.jwt-secret=$JWT_SECRET \
--rollup.config=./rollup.json \
--sequencer.enabled=$SEQUENCER_ENABLED \
--sequencer.stopped=$SEQUENCER_STOPPED \
--sequencer.max-safe-lag=3600 \
--verifier.l1-confs=4 \
--p2p.listen.ip=0.0.0.0 \
--p2p.listen.tcp=$P2P_LISTEN_PORT \
--p2p.listen.udp=$P2P_LISTEN_PORT \
--p2p.advertise.ip=$P2P_ADVERTISE_IP \
--p2p.advertise.tcp=$P2P_LISTEN_PORT \
--p2p.advertise.udp=$P2P_LISTEN_PORT \
--p2p.sequencer.key=$SEQUENCER_PRIVATE_KEY \
--rpc.addr=0.0.0.0 \
--rpc.port=$OP_NODE_RPC_PORT \
--rpc.enable-admin \
--log.level=info \
--log.format=json
Initializing and starting the sequencer
1. Initialize op-geth with your genesis file
# Make sure you're in the sequencer-node directory
cd ~/sequencer-node
# Initialize op-geth with your genesis file
../op-geth/build/bin/geth init --datadir=./data/op-geth --state.scheme=hash ./genesis.json
2. Start op-geth
# Make scripts executable
chmod +x scripts/start-op-geth.sh
chmod +x scripts/start-op-node.sh
# Start op-geth in the background or in a separate terminal
./scripts/start-op-geth.sh
Note: You should see output indicating that op-geth is starting and listening on the configured ports.
3. Start op-node
# In a separate terminal, navigate to the sequencer directory
cd ~/sequencer-node
# Start op-node
./scripts/start-op-node.sh
4. Verify sequencer is running
Once both services are running, verify they're working correctly:
# Check op-geth is responding
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://localhost:8545
# Check op-node is responding
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"optimism_version","params":[],"id":1}' \
http://localhost:8547
# Check sequencer status
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' \
http://localhost:8547
5. Enable sequencing (if started in stopped state)
If you started with SEQUENCER_STOPPED=true
, enable sequencing:
# Use the admin RPC to start sequencing
curl -X POST http://localhost:8547 \
-H "Content-Type: application/json" \
-d '{"method":"admin_startSequencer","params":[],"id":1,"jsonrpc":"2.0"}'
Your sequencer node is now operational and ready to process transactions.