Quick Start

Hosts turn raw blockchain data into structured Views and produce Attestation Records that help secure the network. This guide covers installing, configuring, and running the Shinzo Host 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 Host 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 Host 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 DefraDB node. Defaults work for most setups.
  • defradb.keyring_secret: Requires a secret to generate your private keys.
  • p2p.bootstrap_peers: Indexer 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 DefraDB data is stored.
  • shinzo.web_socket_url: Defaults to a hosted ShinzoHub node. Only change if connecting to a different node.
  • logger.development: Set to false for production.
  • host.lens_registry_path: Where received WASM lens files are stored.
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 indexer, you can connect your Host to this indexer 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 indexer peer.

If you are running both Indexer and Host on the same machine, apply the following changes to the Host's config.yaml to avoid port collisions.

The Indexer 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 Host doesn't clash with the Indexer:

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 host ships with an optional web-based GraphQL Playground for querying the embedded DefraDB instance.

make build-playground
make start

This runs the Host and exposes a Playground GUI. Check the output logs for the address:

🧪 GraphQL Playground available at ...

The playground lets you run GraphQL queries against primitive data and any Views your Host 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
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 host binary (Go 1.25) along with the Wasmtime and Wasmer WASM 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 host. Registration identifies your node so it can replicate data and earn rewards. An unregistered host will not be recognized by the network. There are two ways to register:

Option A: Register with the GUI

  1. Start your Host.
  2. 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: SHNZ
  1. Open the registration route and connect your wallet.
  2. On the registration page, click Register and select "Host" 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 host 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 host is now registered and authorized to participate in the Shinzo Network.

Need Help

If you run into issues installing or running the Shinzo Host, open a GitHub issue here.

Next Steps

Your host can now receive and serve Views. Try running queries against it through the playground GUI.