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
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 8 vCPUs | 16 vCPUs |
| Memory (RAM) | 16 GB | 32–64 GB |
| Storage | 3 TB NVMe | 4+ TB NVMe |
| OS | Ubuntu 24.04 | Ubuntu 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 tofalsefor 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
444open 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
- 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..
- Add Shinzo Devnet to Metamask with the following values:
- Network name: Shinzo
- Default RPC URL: http://rpc.devnet.shinzo.network:8545
- Chain ID: 91273002
- Currency symbol: SHN
- Open the registration route and connect your wallet.
- 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.
- 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.
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.