How to run a normal sequencer node for an Orbit chain
The following instructions are meant for Arbitrum Orbit chains only. This article only applies to test environments. If you need support spinning up a production Orbit chain, we recommend contacting a provider.
We also provide a guide for running a high-availability sequencer node for an Orbit chain. You can find it here.
This how-to provides step-by-step instructions for running a sequencer node on your local machine.
Minimum hardware configuration
The following are the minimum hardware configurations required to set up a Nitro full node (not archival):
Resource | Recommended |
---|---|
RAM | 16 GB |
CPU | 4 core CPU (for AWS, a t3 xLarge instance) |
Storage type | NVMe SSD drives are recommended |
Storage size | Depends on the chain and its traffic overtime |
Please note that:
- These minimum requirements for RAM and CPU are recommended for nodes that process a small amount of RPC requests. For nodes that require processing multiple simultaneous requests, both RAM and the number of CPU cores will need to scale with the amount of traffic served.
- Single core performance is important. If the node is falling behind and a single core is 100% busy, it is recommended to update to a faster processor
- The minimum storage requirements will change over time as the chain grows. Using more than the minimum requirements to run a robust full node is recommended.
Recommended Nitro version
Even though there are alpha and beta versions of the Arbitrum Nitro software, only use release versions when running your node. Running alpha or beta versions is unsupported and might lead to unexpected behaviors.
Latest Docker image: offchainlabs/nitro-node:v3.5.5-90ee45c
Required parameters
1. Sequencer node parameters
The following parameters are required to run a sequencer node:
1. Enable sequencer
Enable the sequencer mode:
--node.sequencer=true
2. Make the node act as a sequencer and post to L1
Enable the sequencer execution:
--execution.sequencer.enable=true
--execution.sequencer.max-tx-data-size=85000
3. Enable delayed sequencer
Enable your node to read and include transactions from the parent chain delayed inbox.
--node.delayed-sequencer.enable=true
--node.delayed-sequencer.use-merge-finality=false
--node.delayed-sequencer.finalize-distance=1
4. Enable batch poster
Enable your node to send batches to the parent chain:
--node.batch-poster.enable=true
--node.batch-poster.max-size=90000
--node.batch-poster.parent-chain-wallet.private-key=<Your Parent Chain Wallet Private Key>
4. Disable transaction forwarding
Disable your sequencer's forwarding transactions, as the node will queue the transaction directly:
--execution.forwarding-target=""
5. Enable feed-out queued transactions
Enable your node to feed out transactions so full node can receive queued transactions:
--node.feed.output.enable=true
--node.feed.output.addr=0.0.0.0
--node.feed.output.port=<Sequencer feed port>
5. Connect the node to data availability servers
This step is only required in Anytrust mode.
Enable your node to send batches to DAS and get DACerts from them.
--node.data-availability.enable=true
--node.data-availability.sequencer-inbox-address=<Sequencer Inbox Address>
--node.data-availability.parent-chain-node-url=<Parent Chain Node URL>
--node.data-availability.rest-aggregator.enable=true
--node.data-availability.rest-aggregator.urls=<A list of DAS REST endpoints, can be only one URL>
--node.data-availability.rpc-aggregator.enable=true
--node.data-availability.rpc-aggregator.assumed-honest=1
--node.data-availability.rpc-aggregator.backends=<A list of RPC backends>
2. Putting it all together
-
When running a Docker image, an external volume should be mounted to persist the database across restarts. The mount point inside the Docker image should be
/home/user/.arbitrum
-
Example:
docker run --rm -it -v /some/local/dir/arbitrum:/home/user/.arbitrum -p 0.0.0.0:8547:8547 -p 0.0.0.0:8548:8548 offchainlabs/nitro-node:v3.5.5-90ee45c --node.sequencer=true --node.delayed-sequencer.enable=true --node.delayed-sequencer.use-merge-finality=false --node.delayed-sequencer.finalize-distance=1 --node.batch-poster.enable=true --node.batch-poster.max-size=90000 --node.batch-poster.parent-chain-wallet.private-key=<Your Parent Chain Wallet Private Key> --node.staker.enable=true --node.staker.strategy=MakeNodes --node.staker.parent-chain-wallet.private-key=<Your Parent Chain Wallet Private Key> --node.data-availability.enable=true --node.data-availability.sequencer-inbox-address=<Sequencer Inbox Address> --node.data-availability.parent-chain-node-url=<Parent Chain Node URL> --node.data-availability.rest-aggregator.enable=true --node.data-availability.rest-aggregator.urls=<A list of DAS REST endpoints, can be only one URL> --node.data-availability.rpc-aggregator.enable=true --node.data-availability.rpc-aggregator.assumed-honest=1 --node.data-availability.rpc-aggregator.backends=<A list of RPC backends> --execution.sequencer.enable=true --execution.sequencer.max-tx-data-size=85000
- Ensure that
/some/local/dir/arbitrum
already exists; otherwise, the directory might be created withroot
as owner, and the Docker container won't be able to write to it.
- Ensure that
-
Json Example:
{
"node": {
"sequencer": true,
"delayed-sequencer": {
"enable": true,
"use-merge-finality": false,
"finalize-distance": 1
},
"batch-poster": {
"max-size": 90000,
"enable": true,
"parent-chain-wallet": {
"private-key": "<batch post key>"
}
},
"feed": {
"output": {
"enable": true,
"addr": "0.0.0.0",
"port": "<Sequencer feed port>"
}
},
"data-availability": {
"enable": true,
"sequencer-inbox-address": "<Sequencer inbox address>",
"parent-chain-node-url": "https://sepolia-rollup.arbitrum.io/rpc",
"rest-aggregator": {
"enable": true,
"urls": ["http://das-server:9877"]
},
"rpc-aggregator": {
"enable": true,
"assumed-honest": 1,
"backends": "[{\"url\":\"http://das-server:9876\",\"pubkey\":\"YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\"signermask\":1}]"
}
}
},
"execution": {
"forwarding-target": "",
"sequencer": {
"enable": true,
"max-tx-data-size": 85000
}
}
}
Note on permissions
- The Docker image is configured to run as non-root
UID 1000
. If you are running Linux or macOS and you are getting permission errors when trying to run the Docker image, run this command to allow all users to update the persistent folders:
mkdir /data/arbitrum
chmod -fR 777 /data/arbitrum
Optional parameters
Here's a list of the parameters that are most commonly used when running your Orbit sequencer node. You can also use the flag --help
for a comprehensive list of available parameters.
Flag | Description |
---|---|
--execution.rpc.classic-redirect=<RPC> | Redirects archive requests for pre-nitro blocks to this RPC of an Arbitrum Classic node with an archive database, only for Arbitrum One. |
--execution.rpc.classic-redirect=<RPC> | Redirects archive requests for pre-nitro blocks to this RPC from an Arbitrum Classic node with an archive database, only for Arbitrum One. |
--http.api | Which APIs need to be opened over the HTTP-RPC interface. Default: net,web3,eth,arb . Add debug for tracing. |
--http.corsdomain | Accepts cross origin requests from these comma-separated domains (browser enforced). |
--http.vhosts | Accepts requests from these comma-separated virtual hostnames (server enforced). Default: localhost . Accepts * . |
--http.addr | Address to bind RPC to. May require 0.0.0.0 for Docker networking. |
--execution.caching.archive | Will retain past block state. For archive nodes. |
--node.feed.input.url=<feed address> | Default: wss://<chainName>.arbitrum.io/feed . ⚠️ One feed relay per datacenter is advised. See feed relay guide. |
--execution.rpc.evm-timeout | Default: 5s . Timeout for eth_call . (0 == no timeout). |
--execution.rpc.gas-cap | Default: 50000000 . Gas cap for eth_call /estimateGas . (0 = no cap). |
--execution.rpc.tx-fee-cap | Default: 1 . Transaction fee cap (in ETH ) for RPC APIs. (0 = no cap). |
--ipc.path | Filename for IPC socket/pipe within datadir . Not supported on macOS. Note: The path is within the Docker container. |
--init.prune | Prunes database before starting the node. It can be used for full or validator nodes. |
--init.url="<snapshot file>" | Non-Orbit Nitro nodes only: URL from which to download the genesis database. Required only for the first startup of an Arbitrum One node. Reference to snapshots and archive node guide. |
--init.download-path="/path/to/dir" | Non-Orbit Nitro nodes only: Temporarily saves the downloaded database snapshot. Defaults to /tmp/ . Used with --init.url . |
--node.batch-poster.post-4844-blobs | Boolean. Default: false . Used to enable or disable the posting of transaction data using Blobs to Ethereum mainnet. If using calldata is more expensive and the parent chain supports EIP4844 blobs, the batch poster will use blobs when this flag is set to true . It can be set to true or false . |
--node.batch-poster.ignore-blob-price | Boolean. Default: false . If the parent chain supports EIP4844 blobs and ignore-blob-price is set to true , the batch poster will use EIP4844 blobs even if using calldata is cheaper. It can be set to true or false . |
--execution.sequencer.enable | Act as sequencer and post to L1. |
--execution.sequencer.enable-profiling | Enable CPU profiling and tracing. |
--execution.sequencer.expected-surplus-hard-threshold | If the expected surplus is lower than this value, new incoming transactions will be denied (default "default"). |
--execution.sequencer.expected-surplus-soft-threshold | Warnings are posted if the expected surplus is lower than this value (default "default"). |
--execution.sequencer.forwarder.connection-timeout | Total time to wait before canceling connection (default 30s). |
--execution.sequencer.forwarder.idle-connection-timeout | Time until idle connections are closed (default 1m0s). |
--execution.sequencer.forwarder.max-idle-connections | Maximum number of idle connections to keep open (default 100 ). |
--execution.sequencer.forwarder.redis-url | The recommended Redis URL to use as target. |
--execution.sequencer.forwarder.retry-interval | Minimal time between update retries (default 100ms). |
--execution.sequencer.forwarder.update-interval | Forwarding target update interval (default 1s). |
--execution.sequencer.max-acceptable-timestamp-delta | Maximum acceptable time difference between the local time and the latest L1 block's timestamp (default 1h0m0s). |
--execution.sequencer.max-block-speed | Minimum delay between blocks (sets a maximum speed of block production) (default 250ms). |
--execution.sequencer.max-revert-gas-reject | Maximum gas executed in a revert for the sequencer to reject the transaction instead of posting it (anti-DOS). |
--execution.sequencer.max-tx-data-size | Maximum transaction size the sequencer will accept (default 95000 ). |
--execution.sequencer.nonce-cache-size | Size of the transaction sender nonce cache (default 1024 ). |
--execution.sequencer.nonce-failure-cache-expiry | Maximum time to wait for a predecessor before rejecting a transaction whose nonce is too high (default 1s). |
--execution.sequencer.nonce-failure-cache-size | Number of transactions whose nonce is too high to keep in memory while waiting for their predecessor (default 1024 ). |
--execution.sequencer.queue-size | Size of the pending transaction queue (default 1024 ). |
--execution.sequencer.queue-timeout | Maximum time a transaction can wait in a queue (default 12s). |
--execution.sequencer.sender-whitelist | Comma-separated allowlist of authorized senders (if empty, every sender is allowed). |
--node.delayed-sequencer.finalize-distance | Number of blocks in the past L1 block for the transaction to be considered final. This value is ignored when using merge finality. Default: 20 . |
--node.delayed-sequencer.require-full-finality | Whether to wait for full finality before sequencing delayed messages. |
--node.delayed-sequencer.use-merge-finality | Whether to use The Merge's notion of finality before sequencing delayed messages (default to true ). |