Skip to main content

Running a Shinzo indexer

This page covers installing a Shinzo IndexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. with Docker or from source. To complete an indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. setup, you must also register it with the Shinzo Network (see Registration).

Hardware recommendations

ComponentMinimumRecommended
CPU8 vCPUs16 vCPUs
Memory (RAM)16 GB32–64 GB
Storage3 TB NVMe4+ TB NVMe
OSUbuntu 24.04Ubuntu 26.04

Using Docker

These steps use Docker to run the Shinzo IndexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication.. To build the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. from source, see Building from source below.

Prerequisites

  • Docker.
  • Access to an Ethereum execution node that exposes JSON-RPC and WebSocket. The indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. does not run a node for you, it just reads from one. This can be a node you run yourself, a node co-located with your validatorValidator An entity that participates in a chain's consensus. On Ethereum, a validator's withdrawal key signs an EIP-712 message on the outpost to authorize an operator key as its indexer., or a managed provider.
  • A browser wallet setup. This wallet does not need to hold any funds.

Steps

  1. Pull the pre-built indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. image from the Shinzo container registry.

    docker pull ghcr.io/shinzonetwork/shinzo-indexer-client:standard
    standard: Pulling from shinzonetwork/shinzo-indexer-client
    2521f1b70bf8: Pull complete
    2c845527b24c: Pull complete

    [...]

    Digest: sha256:a272b09607e6f3f07399d72d019f058919ba2854469835b80478fd75799fa0fd
    Status: Downloaded newer image for ghcr.io/shinzonetwork/shinzo-indexer-client:standard
  2. Gather your GethGeth Go-Ethereum, the Go implementation of an Ethereum node. Each indexer runs alongside a Geth node and connects over WebSocket (port 8546) and JSON-RPC (port 8545) to fetch block data. node's:

    • RPC URL
    • WebSocket URL
    • API key (if set)
  3. Start the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. by filling in your details and running:

    docker run --rm \
    -e GETH_RPC_URL={{ YOUR RPC URL }}\
    -e GETH_WS_URL={{ YOUR WEBSOCKET URL }}\
    -e GETH_API_KEY={{ YOUR API KEY (OPTIONAL) }} \
    -e INDEXER_START_HEIGHT=0 \
    -e DEFRADB_KEYRING_SECRET=devnet-secret \
    -e DEFRADB_PLAYGROUND=true \
    -e DEFRADB_P2P_ENABLED=true \
    -e DEFRADB_P2P_LISTEN_ADDR=/ip4/0.0.0.0/tcp/9171 \
    -e LOGGER_DEBUG=true \
    -p 9181:9181 \
    -p 9171:9171 \
    -p 8080:8080 \
    ghcr.io/shinzonetwork/shinzo-indexer-client:standard

You should see the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. connect to GethGeth Go-Ethereum, the Go implementation of an Ethereum node. Each indexer runs alongside a Geth node and connects over WebSocket (port 8546) and JSON-RPC (port 8545) to fetch block data. and start collecting and committing blocks:

2026-05-11T10:59:54.762Z INFO Committed block 25071330 (ID: bae-235bbc36-32ff-5fb0-8361-6c4dc3d6aeb9)
2026-05-11T10:59:54.902Z DEBUG HTTP response: 200 OK (Content-Length: )
2026-05-11T10:59:54.902Z DEBUG HTTP request successful, status: 200 OK
2026-05-11T10:59:55.272Z DEBUG HTTP Request: POST http://35.193.228.182:8080
2026-05-11T10:59:55.272Z DEBUG Setting x-goog-api-key header: df7f****e6db
2026-05-11T10:59:55.272Z DEBUG Request headers: Content-Type=application/json, User-Agent=
2026-05-11T10:59:55.409Z DEBUG HTTP response: 200 OK (Content-Length: )
2026-05-11T10:59:55.409Z DEBUG HTTP request successful, status: 200 OK

Eventually your indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. will catch up with the validatorValidator An entity that participates in a chain's consensus. On Ethereum, a validator's withdrawal key signs an EIP-712 message on the outpost to authorize an operator key as its indexer. node and start waiting for new blocks rather than pulling historical data:

2026-05-11T11:05:09.338Z DEBUG HTTP response: 200 OK (Content-Length: )
2026-05-11T11:05:09.338Z DEBUG HTTP request successful, status: 200 OK
2026-05-11T11:05:09.338Z INFO Block 25071451 not available yet, waiting...

Registration

Once the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. is running, register it with the Shinzo Network. See Registration for details.

Building from source

You can also build the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. binary from source instead of using Docker.

Prerequisites

Steps

  1. Clone the repository and install the Go dependencies.

    git clone https://github.com/shinzonetwork/shinzo-indexer-client.git
    cd shinzo-indexer-client
    go mod download
  2. Create a .env file with your node details and indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. settings.

    cat > .env << EOF
    GETH_RPC_URL=<your-rpc-url>
    GETH_WS_URL=<your-ws-url>
    GETH_API_KEY=<your-api-key>

    DEFRADB_KEYRING_SECRET=<your-keyring-secret>
    DEFRADB_PLAYGROUND=true
    DEFRADB_P2P_ENABLED=true
    DEFRADB_P2P_LISTEN_ADDR=/ip4/0.0.0.0/tcp/9171

    INDEXER_START_HEIGHT=0
    LOGGER_DEBUG=true
    EOF

    You may not need to enter a Geth API key.

  3. Build the binary. The default build uses a non-branchable schema and processes transactions in parallel.

    make build

    If you need sequential processing with DefraDBdefraDB A peer-to-peer, document-oriented database embedded in every indexer and host. It handles storage, content addressing, CRDT merging, query serving, and P2P replication via libp2p. branchable collections, pass the branchable tag instead:

    make build TAGS=branchable
  4. Run the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication..

    make start
info

The included config.yaml works for most local development. You typically only need to change peer settings or storage paths for advanced setups. Environment variables in .env override values in config.yaml.

Registration

Once your indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. is running, register it with the Shinzo Network. See Registration for details.

Do you need an API key?

It depends on where your GethGeth Go-Ethereum, the Go implementation of an Ethereum node. Each indexer runs alongside a Geth node and connects over WebSocket (port 8546) and JSON-RPC (port 8545) to fetch block data. node is.

If the indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. and the GethGeth Go-Ethereum, the Go implementation of an Ethereum node. Each indexer runs alongside a Geth node and connects over WebSocket (port 8546) and JSON-RPC (port 8545) to fetch block data. node are on the same private network (both on VMs in the same VPC, for example) you probably don't need one. GethGeth Go-Ethereum, the Go implementation of an Ethereum node. Each indexer runs alongside a Geth node and connects over WebSocket (port 8546) and JSON-RPC (port 8545) to fetch block data. has no authentication by default. Leave GETH_API_KEY empty and point GETH_RPC_URL at the node's internal IP or hostname.

If you are connecting to an externally hosted node, authentication is almost always required. Two common cases:

  • GCP Blockchain Node Engine (blockchainnodeengine.com) expects the API key in the X-goog-api-key header.
  • A self-hosted node behind a reverse proxy (e.g. nginx) uses whatever header the operator configures. X-Api-Key is common.

The indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. picks the right header automatically based on the URL.

Exposed ports

The following ports must be exposed and available on the machine.

PortService
8080Health endpoint (/health), metrics (/metrics), and registration ('/registration').
9171DefraDBdefraDB A peer-to-peer, document-oriented database embedded in every indexer and host. It handles storage, content addressing, CRDT merging, query serving, and P2P replication via libp2p. P2P.
9181DefraDBdefraDB A peer-to-peer, document-oriented database embedded in every indexer and host. It handles storage, content addressing, CRDT merging, query serving, and P2P replication via libp2p. GraphQL API.

Troubleshooting

Permission denied on .defra/keys

The data directories are owned by root but the container runs as UID 1001. Stop the container, fix the ownership, then start again:

docker-compose -f ~/docker-compose.yml stop
chown -R 1001:1001 ~/data/defradb ~/data/lens
docker-compose -f ~/docker-compose.yml start

Failed to load existing DefraDB identity

DEFRADB_KEYRING_SECRET has changed since the first run. Restore the original value in your compose file and restart.

WebSocket unavailable, will use HTTP-only mode

The indexerIndexer A node that reads blockchain data from a source chain, parses it into structured documents, and writes them to defraDB. Indexers are write-only: they push data out over P2P and reject all incoming replication. falls back to HTTP polling. Check that GETH_WS_URL is correct and the port is reachable. HTTP-only mode works but is slightly slower.