How to run a full node for an Arbitrum chain
If you’re interested in accessing an Arbitrum chain but don’t want to set up your own node, see our Node Providers to get RPC access to fully managed nodes hosted by a third-party provider.
This how-to provides step-by-step instructions for running a full node for Arbitrum on your local machine.
Prerequisites
In addition to the hardware requirements, the following prerequisites will be necessary when initially setting up your node. It is essential not to skip over these items. You would benefit by copying and pasting them into a notepad or text editor, as you will need to combine them with other commands and configuration/parameter options when you initially run your Arbitrum node.
Minimum hardware configuration
The following are the minimum hardware requirements to set up a Nitro full node (not archival):
| Resource | Minimum requirements | Recommended |
|---|---|---|
| RAM (DDR5) | 64 GB | 128 GB or more |
| CPU | 8 core 3rd generation CPUs (for AWS, a i4i.2xlarge instance) | 16 core CPU or higher and more recent/newer generation of CPUs |
| Storage type | NVMe SSD drives with locally attached drives strongly recommended | Same |
| Storage size | Depends on the chain and its traffic over time, but ideally several terabytes (TB) | Same, but higher if possible |
Please note that:
- The minimum requirements for RAM and CPU listed here are recommended for nodes that handle a limited number of RPC requests. For nodes that need to process multiple simultaneous requests, both the RAM size and the number of CPU cores should be increased to accommodate higher levels of traffic.
- Single core performance is important. If the node is falling behind and a single core is 100% busy, the recommendation is to upgrade 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. Note that snapshot extraction requires approximately 2x the snapshot size in temporary disk space, so plan accordingly during initial setup.
- Path-based state schemes are supported for Nitro's state trie, but only for full nodes and archive nodes at this time, and not validators yet. As a result, HashDB is still the default state scheme used by Nitro, and you must take explicit action to enable PathDB. You can find more details in the table below for optional parameters.
Parent chain (L1) client
Your Arbitrum node requires a connection to a parent chain RPC endpoint (e.g., an Ethereum execution client for Arbitrum One or Nova). Keep your parent chain client up to date—incompatible L1 client versions can cause your Arbitrum node to crash or fail to sync. When upgrading your L1 client, check the Nitro release notes for any noted compatibility requirements.
Recommended Nitro version
Although there are beta and release candidate versions of the Arbitrum Nitro software, use only the release version when running your node. Running beta or RC versions is not supported and might lead to unexpected behaviors and/or database corruption.
Latest Docker image: offchainlabs/nitro-node:v3.9.8-4624977
Database snapshots
Database snapshots are available and located in the snapshot explorer for Arbitrum One, Arbitrum Nova, and Arbitrum Sepolia. Currently, only archive node snapshots using PathDB are available for Arbitrum One and Arbitrum Sepolia. Pruned PathDB snapshots for full nodes on Arbitrum One and Arbitrum Sepolia will be uploaded soon.
Database snapshots for other Arbitrum chains may be available at the discretion of the chain's team. Get in touch with them if you're interested in using a database snapshot for their chains.
Supplying a database snapshot when starting your node for the first time is required for Arbitrum One (to provide information from the Classic era) but is optional for other chains. Supplying a database snapshot on the first run will provide the state and data for that chain up to a specific block, allowing the node to sync faster to the head of the chain.
We provide a summary of the available parameters here, but we recommend reading the complete guide if you plan to use snapshots.
- Use the parameter
--init.latest <snapshot type>(accepted values:archive,pruned,genesis) to instruct your node to download the corresponding snapshot from the configured URL - Optionally, use the parameter
--init.latest-baseto set the base URL when searching for the latest snapshot - Note that these parameters get ignored if a database already exists
- When running more than one node, it's easier to manually download the different parts of the snapshot, join them into a single archive, and host it locally for your nodes. Please see Downloading the snapshot manually for instructions on how to do that.
- Only snapshots formatted with your node's specified state scheme are compatible. In other words, a PathDB snapshot won't work for a node using HashDB, and vice versa.
| Scenario | Recommended Parameter |
|---|---|
| Setting up a new pruned (full) node | --init.latest pruned |
| Setting up a new archive node | --init.latest archive (note: the publicly hosted archive snapshot may be outdated as it has not been updated recently) |
| Reducing disk usage on an existing node | --init.prune full (or minimal) — only applicable to HashDB; PathDB handles state trie pruning automatically |
| Hosting one snapshot for multiple nodes | Download manually, then use --init.url file:///path/to/archive.tar on each node |
| Using a custom snapshot URL | --init.url https://your-snapshot-url/archive.tar |
For more details on snapshot downloading and initialization, see the complete snapshot guide.
If running a beacon node, historical data will now be in blobs. To make this transition to using historical blobs refer to the Historical Blobs for Beacon Nodes guide.
Required parameters
The following list contains all the parameters needed to configure your node. Select the appropriate option depending on the chain you want to run your node for.
- Arbitrum One, Nova, Sepolia
- Arbitrum chains
1. Parent chain (Ethereum) parameters
The --parent-chain.connection.url parameter needs to provide a standard RPC endpoint for an Ethereum node, whether self-hosted or obtained from a node service provider:
--parent-chain.connection.url=<Ethereum RPC URL>
Additionally, use the parameter --parent-chain.blob-client.beacon-url to provide a beacon chain RPC endpoint:
--parent-chain.blob-client.beacon-url=<Ethereum beacon chain RPC URL>
If you choose to self-host an EVM node, the Prysm client software is a great choice. It's straightforward, efficient, and effective—ensuring your setup runs smoothly!
You can also consult our list of Ethereum beacon chain RPC providers. Note that historical blob data is required for these chains to properly sync up if they are new or have been offline for more than 18 days. The beacon chain RPC endpoint you use may also need to provide historical blob data. Please see Special notes on ArbOS 20: Atlas support for EIP-4844 for more details.
2. Arbitrum chain parameters
Use the parameter --chain.id to specify the chain you're running this node for. See RPC endpoints and providers to find the IDs of these chains.
--chain.id=<Arbitrum chain ID>
Alternatively, you can use the parameter --chain.name to specify the chain you're running this node for. Use arb1 for Arbitrum One, nova for Arbitrum Nova, or sepolia-rollup for Arbitrum Sepolia.
--chain.name=<Child chain name>
1. Parent chain parameters
The --parent-chain.connection.url parameter needs to provide a standard RPC endpoint for an EVM node, whether self-hosted or obtained from a node service provider:
--parent-chain.connection.url=<Parent chain RPC URL>
If you choose to self-host an EVM node, the Prysm client software is a great choice. It's straightforward, efficient, and effective—ensuring your setup runs smoothly!
Additionally, if the chain is a Layer-2 (L2) chain on top of Ethereum and uses blobs to post calldata, use the parameter --parent-chain.blob-client.beacon-url to provide a beacon chain RPC endpoint:
--parent-chain.blob-client.beacon-url=<Parent chain beacon chain RPC URL>
Public Arbitrum RPC endpoints rate-limit connections. To avoid hitting a bottleneck, you can run a local node for the parent chain or rely on third-party RPC providers.
You can find beacon providers in our list of Ethereum beacon chain RPC providers. Note that historical blob data is required for these chains to properly sync up if they are new or have been offline for more than 18 days. This means that the beacon chain RPC endpoint you use may also need to provide historical blob data. Please see Special notes on ArbOS 20: Atlas support for EIP-4844 for more details.
2. Child chain parameters
The parameter --chain.info-json specifies a JSON string that contains the information about the Arbitrum chain required by the node.
--chain.info-json=<Orbit chain's info>
This information should be provided by the chain owner and will look something like the following:
--chain.info-json="[{\"chain-id\":94692861356,\"parent-chain-id\":421614,\"chain-name\":\"My Arbitrum L3 Chain\",\"chain-config\":{\"chainId\":94692861356,\"homesteadBlock\":0,\"daoForkBlock\":null,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"berlinBlock\":0,\"londonBlock\":0,\"clique\":{\"period\":0,\"epoch\":0},\"arbitrum\":{\"EnableArbOS\":true,\"AllowDebugPrecompiles\":false,\"DataAvailabilityCommittee\":false,\"InitialArbOSVersion\":10,\"InitialChainOwner\":\"0xAde4000C87923244f0e95b41f0e45aa3C02f1Bb2\",\"GenesisBlockNum\":0}},\"rollup\":{\"bridge\":\"0xde835286442c6446E36992c036EFe261AcD87F6d\",\"inbox\":\"0x0592d3861Ea929B5d108d915c36f64EE69418049\",\"sequencer-inbox\":\"0xf9d77199288f00440Ed0f494Adc0005f362c17b1\",\"rollup\":\"0xF5A42aDA664E7c2dFE9DDa4459B927261BF90E09\",\"validator-utils\":\"0xB11EB62DD2B352886A4530A9106fE427844D515f\",\"validator-wallet-creator\":\"0xEb9885B6c0e117D339F47585cC06a2765AaE2E0b\",\"deployed-at\":1764099}}]"
Use the parameter --chain.name to specify the chain you're running this node for. The name of the chain should match the name used in the JSON string used in --chain.info-json:
--chain.name=<Orbit chain name>
3. Parameters to connect to the sequencer
Use the parameter --node.feed.input.url to point at the sequencer feed endpoint, which should be provided by the chain owner.
--node.feed.input.url=<Sequencer feed url>
Use the parameter --execution.forwarding-target to point at the sequencer node of the Arbitrum chain, which should also be provided by the chain owner.
--execution.forwarding-target=<Sequencer node endpoint url>
3. Additional parameters for AnyTrust chains
If you're running a node for an Anytrust chain, you need to specify information about the Data Availability Committee (DAC) in the configuration of your node.
First, enable data-availability using the following parameters:
--node.data-availability.enable
--node.data-availability.rest-aggregator.enable
Then, choose one of these methods to specify the DAS REST endpoints that your node will read the information from. These endpoints should also be provided by the chain owner.
- Set the DAS REST endpoints directly:
--node.data-availability.rest-aggregator.urls=<A list of DAS REST endpoints, separated by commas>
- Set a URL that returns a list of the DAS REST endpoints:
--node.data-availability.rest-aggregator.online-url-list=<A URL that returns a list of the DAS REST endpoints>
If you are a chain owner, please refer to the DAC setup guide to set it up.
Additionally, for your batch poster to post data to the DAS, follow Step 3 of How to configure a DAC to configure your batch poster node.
Putting it into practice: run a node
If you are running more than one node, you should run a feed relay.
To ensure the database persists across restarts, mount an external volume to /home/user/.arbitrum inside the Docker container. Make sure to:
- Create the host directory before running Docker (e.g.,
mkdir -p /some/local/dir/arbitrum), otherwise Docker may create it asroot, and the container (which runs as UID 1000) won't be able to write to it. - If you encounter permission errors on Linux or macOS, run
chmod -fR 777 /some/local/dir/arbitrumon the host directory.
If using a node-config.json file with Docker to mount, use the following command:
docker run --rm -it -v /Path/to/mount/arbitrum:/home/user/.arbitrum -v /Path/to/node-config.json:/home/user/.arbitrum/node-config.json -p 0.0.0.0:8450:8450 offchainlabs/nitro-node:v3.9.8-4624977 --conf.file /home/user/.arbitrum/node-config.json
- Here is an example of how to run
nitro-node:
- Arbitrum One, Nova, Sepolia
- Arbitrum chains
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.9.8-4624977 --parent-chain.connection.url=<Ethereum RPC URL> --parent-chain.blob-client.beacon-url=<Ethereum beacon chain RPC URL> --chain.id=<Arbitrum chain id> --init.latest=pruned --http.api=net,web3,eth --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
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.9.8-4624977 --parent-chain.connection.url=<Parent chain RPC URL> --chain.info-json=<Orbit chain's info> --chain.name=<Orbit chain name> --node.feed.input.url=<Sequencer feed url> --execution.forwarding-target=<Sequencer node endpoint url> --http.api=net,web3,eth --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
- You can see an example of
--chain.info-jsonin the section above.
-
Note that it is important that
/some/local/dir/arbitrumalready exists; otherwise, the directory might be created withrootas owner, and the Docker container won't be able to write to it. -
Note that if you are running a node for the parent chain (e.g., Ethereum for Arbitrum One or Nova) on localhost, you may need to add
--network hostright afterdocker runto use Docker host-based networking -
When shutting down the Docker image, it is important to allow a graceful shutdown to save the current state to disk. Here is an example of how to do a graceful shutdown of all Docker images currently running
docker stop --time=1800 $(docker ps -aq)
Important ports
| Protocol | Default port |
|---|---|
RPC/http | 8547 |
RPC/websocket | 8548 |
Sequencer Feed | 9642 |
- Please note: the
RPC/websocketprotocol requires some ports to be enabled, you can use the following flags:--ws.port=8548--ws.addr=0.0.0.0--ws.origins=\*
Note on permissions
-
The Docker image is configured to run as non-root UID 1000. This configuration means if you are running in Linux or OSX 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/arbitrumchmod -fR 777 /data/arbitrum
Watchtower mode
- By default, the full node runs in Watchtower mode, meaning that it watches the onchain assertions and, if it disagrees with them, logs an error containing the string
found incorrect assertion in watchtower mode. For a BoLD-enabled chain like Arbitrum One or Arbitrum Nova if you are running Nitro before v3.6.0, the--node.bold.enable=trueflag should be set to ensure your node can monitor for onchain assertions properly. - Setting this flag is not required as your node will continue to operate correctly, validate the Arbitrum One/Nova chain, and serve RPC requests as usual, regardless of this flag.
- Note that watchtower mode adds a small amount of execution and memory overhead. You can deactivate this mode using the parameter
--node.staker.enable=false.
Pruning
By default, all node types will use HashDB, go-ethereum's original state trie storage scheme. This will be the case until a path-based state scheme (e.g., PathDB) is supported across all Arbitrum node types. This means that, by default, pruning will continue to be an manual opt-in operation, should an operator decide to do so. As a refresher, pruning a full node means removing older, unnecessary data from the local copy of the blockchain the node maintains, thereby saving disk space and slightly improving the node's efficiency. Pruning will remove all states from blocks older than the latest 128.
For nodes using PathDB, pruning will be automatic, can be done online, and defaults to retaining only the last 24 hours' worth of state history on disk.
The pruning process occurs when the node starts (upon initialization) and will not serve RPC requests during pruning.
If you are using the default storage scheme (HashDB), then you can activate pruning by using the parameter:
--init.prune <pruning mode>, where<pruning mode>can be one of:minimal: The most aggressive prune and retains only the genesis state and the head state (at the latest snapshot). Takes the least amount of time to complete. Duration depends on the chain and database size (several hours for smaller chains; potentially days for large chains like Arbitrum One).full: Mostly intended for full nodes serving RPC requests, this mode retains the genesis state, the state of the latest confirmed block, and the head state (at the latest snapshot). Will not work if the node is invalidatormode. Duration varies significantly by chain and database size—for Arbitrum One, this may take multiple days on NVMe SSDs. For smaller chains, it will be much faster. If pruning takes too long, consider downloading a fresh pruned snapshot with--init.latest prunedinstead.validator: Meant to be used by validator nodes and requires an RPC URL for L1 Ethereum. This mode retains the genesis state, the state of the latest confirmed block, the latest confirmed assertion root (obtained from L1), the last locally validated block root, and the head state (at the latest snapshot). This mode is expected to take longer thanfullpruning mode.
Memory management
Under heavy RPC load or during operations such as large debug_traceBlockByNumber calls, Nitro nodes can consume significant memory. To prevent out-of-memory (OOM) crashes, consider configuring the following:
--node.resource-mgmt.mem-free-limit: Declines incoming RPC requests when free system memory drops below the specified threshold (e.g.,--node.resource-mgmt.mem-free-limit=4GiB). This helps protect the node from OOM under high request load.GOMEMLIMITenvironment variable: Sets a soft memory limit for the Go runtime garbage collector (e.g.,GOMEMLIMIT=48GiBfor a 64 GB machine), helping reduce memory spikes.
For Docker deployments, you can set these in your docker run command:
docker run ... -e GOMEMLIMIT=48GiB ... offchainlabs/nitro-node:... --node.resource-mgmt.mem-free-limit=4GiB ...
Transaction prechecker
- Enabling the transaction prechecker will add extra checks before your node forwards
eth_sendRawTransactionto the Sequencer endpoint. - Below, we list the flags to set up the prechecker:
| Flag | Description |
|---|---|
--execution.tx-pre-checker.strictness | How strict to be when checking transactions before forwarding them. 0 = accept anything, 10 = should never reject anything that'd succeed, 20 = likely won't reject anything that'd succeed, 30 = full validation which may reject transactions that would succeed (default 20) |
--execution.tx-pre-checker.required-state-age | How long ago should the storage conditions from eth_SendRawTransactionConditional be true, 0 = don't check old state (default 2) |
--execution.tx-pre-checker.required-state-max-blocks | Maximum number of blocks to look back while looking for the <required-state-age> seconds old state, 0 = don't limit the search (default 4) |
Optional parameters
Below, we listed the most commonly used parameters when running a node. You can also use the flag --help for a comprehensive list of the available parameters.
| Flag | Description |
|---|---|
--http.api | Offers APIs 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 | Sets the address to bind RPC to. May require 0.0.0.0 for Docker networking. |
--execution.caching.archive | Retains past block state. For archive nodes. |
--execution.caching.state-scheme | Default: hash. This flag sets the schema used in Nitro’s state trie, inherited from Geth. Teams may choose to set this to the path to enable PathDB, but note that PathDB is not yet supported for validators. |
--execution.caching.state-history | Default: 345600 blocks, calculated as 24 hours worth of blocks at the default block speed of 250ms. Number of recent blocks of state history to retain on disk. Set to 0 for unlimited (i.e. Archive nodes). Only available for PathDB enabled nodes |
--execution.caching.pathdb-max-diff-layers | Default: 128 layers. Maximum number of diff layers kept in the node's memory before flushing to disk. Increasing the number of diff layers may cause the node to fall behind the chain head during busy periods since doing so slows down block processing speed and reduces sync speed. This configuration is primarily used to improve performance of shallow re-orgs (which are a concern on Ethereum but not on Arbitrum chains) and for efficient access to recent state. |
--node.feed.input.url=<feed address> | Sets the sequencer feed address to this URL. Default: wss://<chainName>.arbitrum.io/feed. ⚠️ One feed relay per datacenter is advised. See feed relay guide. |
--execution.forwarding-target=<RPC> | Sets the sequencer endpoint to forward requests to. |
--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 ether) for RPC APIs. (0 = no cap). |
--execution.tx-lookup-limit | Default: 126230400, ~1 year worth of blocks at 250ms/block. Maximum number of blocks from head whose transaction indices are reserved (for example, eth_getTransactionReceipt and eth_getTransactionByHash only return results for indexed transactions). Set to 0 to index transactions for all blocks. Changing this parameter reindexes all missing transactions without the need to resync the chain. |
--execution.rpc.classic-redirect=<RPC> | (Arbitrum One only) Redirects archive requests for pre-nitro blocks to this RPC of an Arbitrum Classic node with archive database. |
--node.resource-mgmt.mem-free-limit | Declines incoming RPC requests when free system memory (excluding page cache) drops below this threshold. Accepts values with suffixes like 4GiB, 512MiB. Helps prevent OOM crashes under heavy load. |
--ipc.path | Filename for IPC socket/pipe within datadir. 🔉 Not supported on macOS. The path is within the Docker container. |
--init.prune | Prunes the database before starting the node. Can be "full" or "validator". |
--init.url="<snapshot file>" | (Required for Arbitrum One) URL to download the genesis database from. Only required for Arbitrum One nodes, when running them for the first time. See the Nitro database snapshots guide for more information. |
--init.download-path="/path/to/dir" | Temporarily saves the downloaded database snapshot. Defaults to /tmp/. Used with --init.url. |
--init.latest | Searches for the latest snapshot of the given kind (accepted values: archive, pruned, genesis) |
--init.latest-base | Base URL used when searching for the latest snapshot. Default: "https://snapshot.arbitrum.foundation/". If you're running an Arbitrum chain, ask the chain owner for this URL. |
--init.then-quit | Allows any --init.* parameters to complete, and then the node automatically quits. It doesn't initiate pruning by itself but works in conjunction with other --init.* parameters, making it easier to script tasks like database backups after initialization processes finish. |