> For the complete documentation index, see [llms.txt](https://docs.gravity.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gravity.xyz/legacy-alpha-mainnet-l2/run-a-gravity-alpha-mainnet-l2-full-node-from-snapshot.md).

# Alpha Mainnet (L2) Full Node from Snapshot

This guide is for operators who want to run a **full node** (non-archive) against Gravity Alpha Mainnet (L2) and would like to skip the multi-day catch-up from the Conduit snapshot. It walks through downloading a public Google Cloud Storage (GCS) snapshot of the chaindata and starting nitro in full-node mode.

If you instead want an archive node — required for full historical `eth_call` / `debug_traceTransaction` against old blocks — follow [Alpha Mainnet (L2) Archive Node Setup](/legacy-alpha-mainnet-l2/run-a-gravity-alpha-mainnet-l2-archive-node.md) instead. The two flows share the same image, chain config, parent-chain URLs, DA committee URL, feed URL, and forwarder; only the snapshot source and a couple of `--execution.caching` flags differ.

## Snapshot

A public, anonymously-readable snapshot of the Gravity Alpha Mainnet (L2) chaindata is hosted on Google Cloud Storage.

| Property                   | Value                                                                                                                                                                    |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| GCS bucket path            | `gs://gravity-public-bucket/nitro-data-20260526/`                                                                                                                        |
| Anonymous HTTPS listing    | [`https://storage.googleapis.com/gravity-public-bucket/?prefix=nitro-data-20260526/`](https://storage.googleapis.com/gravity-public-bucket/?prefix=nitro-data-20260526/) |
| Anonymous file URL pattern | `https://storage.googleapis.com/gravity-public-bucket/nitro-data-20260526/<path>`                                                                                        |
| Total size                 | \~350 GB across 4,803 objects                                                                                                                                            |
| Contents                   | `conduit-orbit-deployer/nitro/` chaindata only — no logs, no keys, no `jwtsecret`                                                                                        |
| Snapshot label / date      | `20260526` (snapshot taken 2026-05-26)                                                                                                                                   |

The bucket is publicly readable. **No Google account is required**, and the snapshot is reachable from `gcloud storage`, `gsutil`, plain `curl`/`wget`, or any S3/GCS-compatible mirror tool.

## Prerequisites

1. A local directory with at least \~400 GB of free space for the chaindata (the snapshot is \~350 GB before nitro's pebble overhead).
2. An Ethereum mainnet RPC endpoint with unlimited rate limit for `eth_getLogs`.
3. An Ethereum beacon chain RPC endpoint.

## Step 1 — Download the snapshot

Pick whichever transfer tool you already have. The `gcloud storage` client is recommended because it parallelises transfers and is resumable; plain `wget` works if you don't want to install `gcloud`.

### Option A — `gcloud storage` (recommended)

```bash
# Install: https://cloud.google.com/sdk/docs/install
# No authentication required for this bucket.
gcloud storage rsync --recursive \
    gs://gravity-public-bucket/nitro-data-20260526/ \
    /path/to/your/datadir/
```

`rsync` is idempotent and safe to re-run if the transfer is interrupted.

### Option B — `gsutil`

```bash
gsutil -m rsync -r \
    gs://gravity-public-bucket/nitro-data-20260526/ \
    /path/to/your/datadir/
```

### Option C — plain HTTPS with `wget`

Anonymous HTTPS works for every object. List the bucket via the XML listing URL, then `wget` each key. Example one-liner using `curl` + `xmllint` to enumerate keys:

```bash
LIST_URL="https://storage.googleapis.com/gravity-public-bucket/?prefix=nitro-data-20260526/"
DEST=/path/to/your/datadir

# Fetch the first page; for full traversal you must also follow <NextMarker> pages.
curl -s "$LIST_URL" \
    | xmllint --xpath '//*[local-name()="Key"]/text()' - \
    | tr ' ' '\n' \
    | while read key; do
        rel="${key#nitro-data-20260526/}"
        mkdir -p "$DEST/$(dirname "$rel")"
        wget -c -O "$DEST/$rel" \
            "https://storage.googleapis.com/gravity-public-bucket/$key"
      done
```

`gcloud storage` is strongly preferred over this loop — it handles pagination, retries, and parallelism for you.

## Step 2 — Post-rsync fixups

Two things need to be fixed up after the rsync, both because `gcloud storage rsync` does not carry over filesystem metadata that nitro relies on.

### Recreate the `geth/chaindata` symlink

The source filesystem has `conduit-orbit-deployer/nitro/geth/chaindata` as a symlink pointing to `../l2chaindata`. `gcloud storage` does not preserve symbolic links and skips otherwise-empty directories, so after the rsync both the symlink and the `geth/` directory that holds it are missing. Recreate both:

```bash
DATADIR=/path/to/your/datadir
cd "$DATADIR/conduit-orbit-deployer/nitro"
mkdir -p geth
cd geth
ln -s ../l2chaindata chaindata
```

### Match the in-container uid

The `offchainlabs/nitro-node` image runs as the in-image user `user` (uid 1000). The rsync wrote the snapshot as the operator's uid, so unless that uid happens to be 1000 the container will exit within a second of launch with `Failed to prepare jwt secret file ... permission denied` when it tries to create `jwtsecret` and `nodekey` under the mounted volume. Match the owning uid:

```bash
sudo chown -R 1000:1000 "$DATADIR"
```

Alternatively, add `--user $(id -u):$(id -g)` to the `docker run` in Step 3 so the container runs as your operator uid instead.

No other fixups are needed — the snapshot does not include `nodekey`, `jwtsecret`, or pebble log files, so nitro will generate them on first start.

## Step 3 — Run the full node

Save the following as `run-gravity-fullnode.sh`, make it executable with `chmod +x run-gravity-fullnode.sh`, and update the TODO variables. The image, chain config, DA committee, and feed are identical to the archive-mode setup.

{% code overflow="wrap" %}

```bash
#!/bin/bash

# Define dependent variables
LOCAL_DIR="TODO"                # Replace with your local directory path (the one you rsynced the snapshot into)
ETH_MAINNET_RPC="TODO"          # Replace with your Ethereum mainnet RPC endpoint
ETH_BEACON_RPC="TODO"           # Replace with your Ethereum beacon chain RPC endpoint
# Also fill in <YOUR_GRAVITY_ALPHA_MAINNET_RPC> below — the upstream Gravity L2 RPC
# to which write transactions submitted to this node are forwarded.

# Run the Docker container
docker run --rm -it -d \
    --add-host=host.docker.internal:host-gateway \
    --name gravity-fullnode \
    -v "$LOCAL_DIR:/home/user/.arbitrum" \
    -p 0.0.0.0:8547:8547 \
    -p 0.0.0.0:8548:8548 \
    offchainlabs/nitro-node:v3.9.5-66e42c4 \
    --parent-chain.connection.url="$ETH_MAINNET_RPC" \
    --chain.id=1625 \
    --chain.name=conduit-orbit-deployer \
    --http.api=net,web3,eth,debug,arb \
    --http.corsdomain="*" \
    --http.addr=0.0.0.0 \
    --http.vhosts="*" \
    --chain.info-json='[
        {
            "chain-id": 1625,
            "parent-chain-id": 1,
            "chain-name": "conduit-orbit-deployer",
            "chain-config": {
                "chainId": 1625,
                "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": true,
                    "InitialArbOSVersion": 11,
                    "InitialChainOwner": "0xd65776c5F9fA552cB5C9556B3e86bF6c376b233b",
                    "GenesisBlockNum": 0
                }
            },
            "rollup": {
                "bridge": "0x7983403dDA368AA7d67145a9b81c5c517F364c42",
                "inbox": "0x7AD2a94BefF3294a31894cFb5ba4206957a53c19",
                "sequencer-inbox": "0x8D99372612e8cFE7163B1a453831Bc40eAeb3cF3",
                "rollup": "0x2807B1d5d94ca823ca7d8642A5F5DDac120ce48f",
                "validator-utils": "0x2b0E04Dc90e3fA58165CB41E2834B44A56E766aF",
                "validator-wallet-creator": "0x9CAd81628aB7D8e239F1A5B497313341578c5F71",
                "deployed-at": 19898364
            }
        }
    ]' \
    --execution.forwarding-target="<YOUR_GRAVITY_ALPHA_MAINNET_RPC>" \
    --node.feed.input.url="wss://relay-gravity-mainnet-0.t.conduit.xyz" \
    --parent-chain.blob-client.beacon-url="$ETH_BEACON_RPC" \
    --node.data-availability.enable=true \
    --node.data-availability.rest-aggregator.enable=true \
    --node.data-availability.rest-aggregator.urls=https://das-gravity-mainnet-0.t.conduit.xyz \
    --node.staker.enable=false
```

{% endcode %}

### What's different from the archive-mode script

Compared to the archive-mode setup in [Alpha Mainnet (L2) Archive Node Setup](/legacy-alpha-mainnet-l2/run-a-gravity-alpha-mainnet-l2-archive-node.md), this command:

* **Removes** `--execution.caching.archive=true` — full nodes only retain recent state.
* **Omits** `--execution.rpc.max-recreate-state-depth=-1` — that flag is only meaningful in archive mode for unlimited historical state recreation.
* Leaves `--execution.rpc.gas-cap=0` off; you may add it back if you want to lift the default RPC gas cap.
* Replace `<YOUR_GRAVITY_ALPHA_MAINNET_RPC>` with whatever upstream RPC you want write transactions forwarded to — the public `https://rpc.gravity.xyz` works (this is what the archive-mode setup hardcodes), or any other Gravity Alpha Mainnet (L2) RPC you operate. This flag is only consulted for outbound write transactions; reads served by this full node never touch the forwarder.
* Everything else — Docker image (`offchainlabs/nitro-node:v3.9.5-66e42c4`), `--chain.id=1625`, `--chain.info-json`, parent-chain URL, blob-client beacon URL, DA committee REST aggregator, and sequencer feed URL — is **identical** to the archive setup.

## Step 4 — Verify the node is healthy

1. Watch the container logs for pebble bringing the cache up:

   ```bash
   docker logs -f gravity-fullnode | grep -E "Allocated cache|created block"
   ```

   The first useful line is `Allocated cache and file handles ... cache=2.00GiB`. Shortly after, `created block l2Block=...` lines should begin scrolling several times per second while the node catches up to tip.
2. Query the local RPC for the head block:

   ```bash
   curl -s -X POST -H "Content-Type: application/json" \
       --data '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}' \
       http://127.0.0.1:8547
   ```

   The returned block number should increase on each call until it converges with the public tip.
3. Confirm there are no `MissingTrieNode` errors during catch-up:

   ```bash
   docker logs gravity-fullnode 2>&1 | grep -i MissingTrieNode || echo "clean"
   ```

   Validated against this snapshot, the node catches up cleanly at roughly seven blocks per second with no `MissingTrieNode` errors.

## Notes

* The snapshot only contains chaindata. The container will generate its own `nodekey`, `jwtsecret`, and logs on first boot.
* The snapshot was prepared in full-node shape; archive-only state tries that would otherwise pad the dataset are not included, so this snapshot is **not** suitable for an archive node. Use the Conduit-hosted snapshot referenced in [Alpha Mainnet (L2) Archive Node Setup](/legacy-alpha-mainnet-l2/run-a-gravity-alpha-mainnet-l2-archive-node.md) if you need archive mode.
* Once started, this node participates in the standard Gravity Alpha Mainnet (L2) Anytrust DA committee and reads ordering from the Conduit sequencer feed — there is no operational difference at the network level from a node bootstrapped via the archive-mode flow.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gravity.xyz/legacy-alpha-mainnet-l2/run-a-gravity-alpha-mainnet-l2-full-node-from-snapshot.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
