Skip to main content

Quick Start

HostsHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. turn raw blockchain data into structured ViewsView A curated, SDL-defined representation of defraDB documents. Views transform raw indexed data into a structured output shape. and produce Attestation Records that help secure the network. This guide covers installing, configuring, and running the Shinzo HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. Client.

Hardware Recommendations

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

Local Deployment

Run the Shinzo HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. Client directly on your local machine for development and testing.

Prerequisites

  • Go 1.25
  • Metamask with a wallet setup. This wallet does not need to hold any funds.

Clone the Repository

git clone https://github.com/shinzonetwork/shinzo-host-client.git
cd shinzo-host-client

Configuration

The HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. Client reads from config.yaml, which comes with working defaults. The only field you need to set is defradb.keyring_secret. Alternatively, you can also set the password as an environment variable to avoid storing it in plaintext:

export DEFRA_KEYRING_SECRET=<make_a_password>

Key Fields

  • defradb.url: API endpoint of your local 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. node. Defaults work for most setups.
  • defradb.keyring_secret: Requires a secret to generate your private keys.
  • p2p.bootstrap_peers: 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. peers for receiving indexed data. Defaults include a reliable bootstrap peer.
  • p2p.listen_addr: Default is suitable for local runs. Override when containerizing.
  • store.path: Directory where local 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. data is stored.
  • shinzo.web_socket_url: Defaults to a hosted ShinzoHubShinzoHub Shinzo's coordination chain: a Cosmos SDK chain (v0.53.4) with an integrated EVM, running CometBFT consensus. It holds the view, host, and indexer registries and the economic layer (staking, pricing, payments). It does not store or serve indexed blockchain data. node. Only change if connecting to a different node.
  • logger.development: Set to false for production.
  • host.lens_registry_path: Where received WASMWASM A portable, sandboxed bytecode format. Lens transforms compile to WASM — typically from Rust or AssemblyScript — and hosts run them via LensVM. lensLens A WASM module that transforms primitive documents (e.g., raw `Log` records) into view documents (e.g., `USDCTransfer`). Lenses must be deterministic: the same input always produces the same output. Hosts run them via LensVM. files are stored.

:::tip Note The included config.yaml works for most local development. You typically only need to change peer settings or storage paths for advanced setups. :::

Running Indexer and Host on the Same Machine

If you are running your own 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., you can connect your HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. to this 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 configuring p2p.bootstrap_peers. To get the required Peer ID, query the registration endpoint:

curl http://localhost:8080/registration

From this information, assemble your peer connection info: /ip4/<your-ip-here>/tcp/9171/p2p/<your-PeerID-here>. Now replace the default peer in p2p.bootstrap_peers with 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. peer.

If you are running both 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 HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. on the same machine, apply the following changes to the Host's config.yaml to avoid port collisions.

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 likely already using port 9181, so update the defradb.url field:

url: "localhost:9182"

Also update the P2P settings to use localhost and a different port so the HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. doesn't clash with 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.:

bootstrap_peers:
- '/ip4/127.0.0.1/tcp/9171/p2p/<PeerID>'
listen_addr: "/ip4/0.0.0.0/tcp/9172"

Build and Run

Option A: Run directly (no build step):

go run cmd/main.go

Option B: Build then run:

make build
make start

(Optional) Enable the GraphQL Playground

The hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. ships with an optional web-based GraphQL Playground for querying the embedded 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. instance.

make build-playground
make start

This runs the HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. and exposes a Playground GUI. Check the output logsLog A document type the indexer produces for event logs emitted during transaction execution. `topics` holds the indexed parameters and `data` holds the non-indexed ones, both as raw hex. ABI decoding happens later, in a lens. for the address:

🧪 GraphQL Playground available at ...

The playground lets you run GraphQL queries against primitive data and any ViewsView A curated, SDL-defined representation of defraDB documents. Views transform raw indexed data into a structured output shape. your HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. is serving. Try this query:

query GetLatestLogs {
Ethereum__Mainnet__Log(
order: { blockNumber: DESC }
limit: 10
) {
address
topics
data
blockNumber
blockHash
transactionHash
transactionIndex
logIndex
removed
}
}

More query examples are available here.

VM Deployment

This is the recommended approach for production and devnet participation. It uses Docker, docker-compose, and Nginx on a virtual machine.

Prerequisites

  • Port 444 open in your firewall/security group.

Install System Dependencies

sudo apt-get update
sudo apt-get install -y docker.io docker-compose nginx

Create the Data Directory

sudo mkdir -p ~/data/defradb ~/data/lens
sudo chown -R 1001:1001 ~/data/defradb ~/data/lens

Generate SSL Certificates

# Generate private key, certificate signing request, and self-signed certificate
set -e &&
sudo mkdir -p ~/ssl &&
sudo openssl genrsa -out ~/ssl/nginx.key 2048 &&
sudo openssl req -new -key ~/ssl/nginx.key -out /tmp/nginx.csr -subj "/C=US/ST=State/L=City/O=Shinzo/OU=Host Client/CN=shinzo.network" &&
sudo openssl x509 -req -days 365 -in /tmp/nginx.csr -signkey ~/ssl/nginx.key -out ~/ssl/nginx.crt &&
sudo rm /tmp/nginx.csr

Write the Configuration File

Create ~/config.yaml. The production config enables performance tuning, peer reconnection, pruning, and optional event filtering. Key values to set:

defradb:
url: "localhost:9181"
keyring_secret: "<YOUR_SECRET>" # Required, change this
p2p:
enabled: true
bootstrap_peers:
- '/ip4/34.63.13.57/tcp/9171/p2p/12D3KooWMYhYNBo4zAi9j7TpyGQJBSvbwSSNkgsMrLs6vHUnFUzY'
listen_addr: "/ip4/0.0.0.0/tcp/9171"
enable_auto_reconnect: true
store:
path: "./.defra"
shinzo:
hub_base_url: rpc.devnet.shinzo.network:26657
minimum_attestations: 1
logger:
development: false
level: "error"
host:
lens_registry_path: "./.defra/lens"
health_server_port: 8080

:::tip Note The full production config is generated automatically by host-prod-setup.sh. See below. :::

Write the Nginx Config

Create ~/nginx.conf:

events { worker_connections 1024; }

http {
map $http_origin $cors_origin {
default "";
"https://explorer.shinzo.network" $http_origin;
}

server {
listen 8080;
server_name _;

add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Origin' always;
add_header 'Access-Control-Max-Age' 3600 always;
add_header 'Vary' 'Origin' always;

location / {
if ($request_method = OPTIONS) { return 204; }
proxy_pass http://shinzo-host:9181;
proxy_set_header Host $host;
}

location = /metrics {
if ($request_method = OPTIONS) { return 204; }
proxy_pass http://shinzo-host:8080/metrics;
proxy_set_header Host $host;
}

location = /api/v0/graphql {
if ($request_method = OPTIONS) { return 204; }
proxy_pass http://shinzo-host:9181/api/v0/graphql;
proxy_set_header Host $host;
}
}
}

Write the docker-compose File

Create ~/docker-compose.yml:

networks:
shinzo-net:
driver: bridge

services:
shinzo-host:
image: ghcr.io/shinzonetwork/shinzo-host-client:standard
user: "1001:1001"
mem_limit: 16g
mem_reservation: 13g
restart: unless-stopped
container_name: shinzo-host
networks:
- shinzo-net
ports:
- "9181:9181" # DefraDB API
- "444:9182" # GraphQL Playground
- "9171:9171" # P2P networking
volumes:
- ~/data/defradb:/app/.defra/data
- ~/data/lens:/app/.lens
- ~/config.yaml:/app/config.yaml:ro
environment:
- DEFRA_URL=0.0.0.0:9181
- GOMEMLIMIT=14GiB
- LOG_LEVEL=error
- LOG_SOURCE=false
- LOG_STACKTRACE=false
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/metrics"]
interval: 15s
timeout: 30s
retries: 10
start_period: 120s

nginx:
image: nginx:alpine
ports:
- "8080:8080"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- shinzo-host
networks:
- shinzo-net
restart: unless-stopped

Start the Host

docker-compose up -d

Monitoring

The health check endpoint is available at:

http://<VM_IP>:8080/metrics

The container health check polls this every 15 seconds. To check container status:

docker ps
docker logs shinzo-host

Docker Image

The multi-stage Dockerfile builds the hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. binary (Go 1.25) along with the WasmtimeWasmtime A WASM runtime written in Rust. The primary runtime used to execute lenses in production hosts. and WasmerWasmer A WASM runtime written in Rust. Viewkit uses it to validate lenses locally before deployment. WASMWASM A portable, sandboxed bytecode format. Lens transforms compile to WASM — typically from Rust or AssemblyScript — and hosts run them via LensVM. runtimes. The production image is based on Ubuntu 24.04 and runs as a non-root shinzo user. Pre-built images are published to:

ghcr.io/shinzonetwork/shinzo-host-client:standard

ShinzoHub Registration

To participate in the Shinzo Network, you must register your hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL.. Registration identifies your node so it can replicate data and earn rewards. An unregistered hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. will not be recognized by the network. There are two ways to register:

Option A: Register with the GUI

  1. Start your HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL..
  2. Add Shinzo Devnet to Metamask with the following values:
  1. Open the registration route and connect your wallet.
  2. On the registration page, click Register and select "HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL." as your role to complete the process.
  3. Submit your registration, then confirm the transaction in MetaMask. You should see a successful registration notification.

Option B: Register with the CLI

You can also register your hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. by submitting the registration transaction directly with Foundry’s cast CLI.

cast send "0x0000000000000000000000000000000000000211" \
"register(bytes,bytes,bytes,bytes,bytes,uint8)" \
"<public_key>" \
"<public_key_signedMessage>" \
"<peer_id>" \
"<peer_id_signedMessage>" \
"<signed_message>" \
"1" \
--rpc-url "http://rpc.devnet.shinzo.network:8545" \
--from "<your_address>" \
--private-key "<your_private_key>" \
--gas-limit 100000

Replace each placeholder with your actual registration values.

warning

Be careful with your private key. Do not commit it to source control, paste it in public channels, or store it in shell history on shared machines.

Your hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. is now registered and authorized to participate in the Shinzo Network.

Need Help

If you run into issues installing or running the Shinzo HostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL., open a GitHub issue here.

Next Steps

Your hostHost A Shinzo node that receives indexed data from indexers over P2P, verifies it, runs lens transforms to produce view documents, and serves those documents over GraphQL. can now receive and serve ViewsView A curated, SDL-defined representation of defraDB documents. Views transform raw indexed data into a structured output shape.. Try running queries against it through the playground GUI.