Builders
Node Operators
Tutorials
Running OP Sepolia from Source

Running an OP Sepolia Node from Source

This tutorial explains how to run an OP Sepolia node from source code. Running an OP Sepolia node from source code is a flexible alternative to using pre-built Docker images.

Building the Source Code

You'll need to build op-node and op-geth from their respective source repositories before you can run a node. Make sure to follow the instructions on Building a Node from Source before continuing.

Hardware Requirements

Hardware requirements for OP Sepolia nodes can vary depending on the type of node you plan to run. Archive nodes generally require significantly more resources than full nodes. Below are suggested minimum hardware requirements for each type of node.

  • 16GB RAM
  • 1TB SSD (full node) or 2TB SSD (archive node)
  • Reasonably modern CPU

Initialize the Data Directory

Unlike OP Mainnet, OP Sepolia does not require a migrated data directory. Instead, like with Ethereum, you'll simply need to initialize the data directory with the OP Sepolia genesis file.

Navigate to the op-geth directory

Find and enter the directory where you built op-geth from source.

Download the genesis file

Download the genesis file from the OP Sepolia networks page.

curl -o op-sepolia-genesis.json -sL https://networks.optimism.io/op-sepolia/genesis.json

Set environment variables

Set the following environment variables:

export DATADIR_PATH=... # Path to the folder where geth data will be stored

Initialize the data directory

Initialize the data directory with the genesis file.

geth init --datadir=$DATADIR op-sepolia-genesis.json

Assess Blob Archiver

Assess if you need to configure a blob archiver service by reading the Configure a Blob Archiver documentation.

Create a JWT Secret

op-geth and op-node communicate over the engine API authrpc. This communication is secured using a shared secret. You will need to generate a shared secret and provide it to both op-geth and op-node when you start them. In this case, the secret takes the form of a 32 byte hex string.

Run the following command to generate a random 32 byte hex string:

openssl rand -hex 32 > jwt.txt

Start op-geth

It's generally easier to start op-geth before starting op-node. You can still start op-geth without yet running op-node, but the op-geth instance will simply not receive any blocks until op-node is started.

Navigate to your op-geth directory

Find the directory where you built the op-geth binary.

Copy in the JWT secret

Copy the JWT secret you generated in a previous step into the op-geth directory.

cp /path/to/jwt.txt .

Set environment variables

Set the following environment variables (if not already set):

export DATADIR_PATH=... # Path to the folder where geth data will be stored

Start op-geth

Use the following command to start op-geth in a default configuration. The JSON-RPC API will become available on port 8545. Refer to the op-geth configuration documentation for more detailed information about available options.

./build/bin/geth \
  --http \
  --http.port=8545 \
  --http.addr=localhost \
  --authrpc.addr=localhost \
  --authrpc.jwtsecret=./jwt.txt \
  --verbosity=3 \
  --rollup.sequencerhttp=https://sepolia-sequencer.optimism.io/ \
  --nodiscover \
  --syncmode=full \
  --maxpeers=0 \
  --op-network=op-sepolia \
  --datadir=$DATADIR_PATH

Start op-node

Once you've started op-geth, you can start op-node. op-node will connect to op-geth and begin synchronizing the OP Sepolia state. op-node will begin sending block payloads to op-geth when it derives enough blocks from Sepolia.

Navigate to your op-node directory

Find the directory where you built the op-node binary.

Copy in the JWT secret

Both op-geth and op-node need to use the same JWT secret. Copy the JWT secret you generated in a previous step into the op-node directory.

cp /path/to/jwt.txt .

Set environment variables

Set the following environment variables:

export L1_RPC_URL=...  # URL for the L1 node to sync from
export L1_RPC_KIND=... # RPC type (alchemy, quicknode, infura, parity, nethermind, debug_geth, erigon, basic, any)
export L1_BEACON_URL=... # URL address for the L1 Beacon-node HTTP endpoint to use.

Start op-node

Use the following command to start op-node in a default configuration. Refer to the op-node configuration documentation for more detailed information about available options.

⚠️

The op-node RPC should not be exposed publicly. If left exposed, it could accidentally expose admin controls to the public internet.

./bin/op-node \
  --l1=$L1_RPC_URL \
  --l1.rpckind=$L1_RPC_KIND \
  --l1.beacon=$L1_BEACON_URL \
  --l2=ws://localhost:8551 \
  --l2.jwt-secret=./jwt.txt \
  --network=op-sepolia \
  --rpc.addr=127.0.0.1 \
  --rpc.port=8547
💡

Some L1 nodes, like Erigon, do not support the eth_getProof RPC method that the op-node uses to load L1 data for certain processing steps. If you are using an L1 node that does not support eth_getProof, you will need to include the --l1.trustrpc flag when starting op-node. Note that this flag will cause op-node to trust the L1 node to provide correct data as it will no longer be able to independently verify the data it receives.

Synchronization

Once you've started op-geth and op-node you should see the two begin to communicate with each other and synchronize the OP Sepolia chain. Initial synchronization can take several hours to complete.

During this time, you will initially observe op-node deriving blocks from Sepolia without sending these blocks to op-geth. This means that op-node is requesting blocks from Sepolia one-by-one and determining the corresponding OP Sepolia blocks that were published to Sepolia. You should see logs like the following from op-node:

INFO [06-26|13:31:20.389] Advancing bq origin                      origin=17171d..1bc69b:8300332 originBehind=false

Once the op-node has derived enough blocks from Sepolia, it will begin sending these blocks to op-geth. You should see logs like the following from op-node:

INFO [06-26|14:00:59.460] Sync progress                            reason="processed safe block derived from L1" l2_finalized=ef93e6..e0f367:4067805 l2_safe=7fe3f6..900127:4068014 l2_unsafe=7fe3f6..900127:4068014 l2_time=1,673,564,096 l1_derived=6079cd..be4231:8301091
INFO [06-26|14:00:59.460] Found next batch                         epoch=8e8a03..11a6de:8301087 batch_epoch=8301087 batch_timestamp=1,673,564,098
INFO [06-26|14:00:59.461] generated attributes in payload queue    txs=1  timestamp=1,673,564,098
INFO [06-26|14:00:59.463] inserted block                           hash=e80dc4..72a759 number=4,068,015 state_root=660ced..043025 timestamp=1,673,564,098 parent=7fe3f6..900127 prev_randao=78e43d..36f07a fee_recipient=0x4200000000000000000000000000000000000011 txs=1  update_safe=true

You should then also begin to see logs like the following from op-geth:

INFO [06-26|14:02:12.974] Imported new potential chain segment     number=4,068,194 hash=a334a0..609a83 blocks=1         txs=1         mgas=0.000  elapsed=1.482ms     mgasps=0.000   age=5mo2w20h dirty=2.31MiB
INFO [06-26|14:02:12.976] Chain head was updated                   number=4,068,194 hash=a334a0..609a83 root=e80f5e..dd06f9 elapsed="188.373µs" age=5mo2w20h
INFO [06-26|14:02:12.982] Starting work on payload                 id=0x5542117d680dbd4e

Next Steps