How to Set Up a Multichain Deployment with Multiple Validators Using Starship

To set up a multichain deployment with multiple validators using Starship, define your chains and validator counts in a Helm values file, then run starship --config <file> install to deploy the topology automatically.

Starship is a Helm-based framework maintained by hyperweb-io that orchestrates full blockchain nodes (Cosmos SDK, Ethereum, Solana, etc.) inside Kubernetes clusters. A multichain deployment with multiple validators is expressed declaratively through a single YAML configuration, allowing you to spin up interconnected networks without manual node configuration or genesis file distribution.

Architecture of Multi-Validator Deployments

Starship automates the entire validator lifecycle through Kubernetes-native primitives. The architecture relies on several key components working in concert to bootstrap networks.

Core Components

  • Helm Chart (starship/charts/devnet): Templates the Kubernetes resources (StatefulSets, Services, ConfigMaps) for each chain. The validator template at templates/chains/cosmos/validator.yaml contains the logic that creates replicas = numValidators-1 additional validators.
  • Exposer Service: A sidecar container running alongside each validator that exposes REST (8081) and gRPC (9099) endpoints, plus an HTTP API for fetching the genesis file (/genesis).
  • Registry: An optional component (templates/registry.yaml) providing unified chain metadata lookup for relayers and external clients.
  • Starship CLI (cmd/starship): Parses the --config flag and orchestrates Helm commands. The entry point is defined in cmd/starship/config.go.
  • Init Scripts: Bash scripts bundled as ConfigMaps (charts/devnet/scripts/create-validator.sh, transfer-tokens.sh, chain-rpc-ready.sh) handle genesis distribution, key recovery, and validator creation automatically.

Prerequisites and Initial Setup

Begin by cloning the repository and installing the required toolchain.

git clone https://github.com/hyperweb-io/starship.git
cd starship
make dev-setup

Ensure you have a Kubernetes cluster available (Docker Desktop, Kind, or cloud-hosted) and create a target namespace:

kubectl create namespace starship-e2e-tests

Configuring the Values File for Multiple Validators

The deployment topology is defined in a Helm values file. To run multiple validators for a single chain, set the numValidators field greater than 1.

Create a configuration file based on the example at starship/tests/e2e/configs/multi-validator.yaml:

name: starship-e2e-tests
version: 1.7.0

chains:
  - id: osmosis-1
    name: osmosis
    numValidators: 2          # Deploys 1 genesis + 1 additional validator

    ports:
      rest: 1313
      rpc: 26653
      exposer: 38083
      faucet: 8000
    resources:
      cpu: "0.3"
      memory: 600M
    faucet:
      type: starship
      concurrency: 2
      resources:
        cpu: "0.1"
        memory: "200M"

registry:
  enabled: true
  ports:
    rest: 8081
    grpc: 9091

When numValidators exceeds 1, the template templates/chains/cosmos/validator.yaml sets podManagementPolicy: Parallel, allowing additional validators to initialize concurrently.

Deploying the Multichain Topology

Execute the deployment using the Starship CLI or the provided Makefile:

make install HELM_FILE=starship/tests/e2e/configs/multi-validator.yaml

This command invokes the CLI, which expands internally to:

helm upgrade --install starship-e2e-tests \
  ./starship/charts/devnet \
  -n starship-e2e-tests \
  -f starship/tests/e2e/configs/multi-validator.yaml

Wait for all pods to reach Ready state:

kubectl -n starship-e2e-tests wait --for=condition=Ready pod --all --timeout=5m

Forward ports to interact with the chain locally:

make port-forward HELM_FILE=starship/tests/e2e/configs/multi-validator.yaml

Verify the genesis endpoint is accessible:

curl -s http://localhost:38083/genesis | jq .chain_id

How Starship Orchestrates Validator Bootstrapping

Starship eliminates manual intervention through a sequence of init containers and post-start hooks defined in validator.yaml.

Genesis Validator Initialization

The first replica (validator-0) acts as the genesis creator:

  1. Initializes the chain home directory with chaind init.
  2. Generates the genesis file and stores it in a shared location.
  3. Publishes the genesis via the exposer service at http://<pod-name>:8081/genesis.

Additional Validator Join Process

Subsequent validators (validator-1, validator-2, etc.) run an init container that performs the following actions (excerpt from validator.yaml lines 80-99):

- name: init-validator
  image: {{ $chain.image }}
  env:
    - name: KEYS_CONFIG
      value: /configs/keys.json
    - name: GENESIS_HOST
      value: {{ $chain.id }}-validator-0
  command: [ "bash", "-c", '
    VAL_INDEX=${HOSTNAME##*-}
    VAL_NAME=$(jq -r ".validators[0].name" $KEYS_CONFIG)-$VAL_INDEX
    $CHAIN_BIN init $VAL_NAME --chain-id $CHAIN_ID
    jq -r ".validators[0].mnemonic" $KEYS_CONFIG |
      $CHAIN_BIN keys add $VAL_NAME --index $VAL_INDEX --recover --keyring-backend="test"
    curl http://$GENESIS_HOST.$NAMESPACE.svc.cluster.local:$GENESIS_PORT/genesis -o $CHAIN_DIR/config/genesis.json
  ' ]

This container:

  • Recovers its private key from the keys.json ConfigMap using the validator index.
  • Fetches the genesis file from the genesis validator's exposer.
  • Configures persistent_peers in config.toml to establish P2P connectivity.

Automated Network Participation

After the container starts, a post-start hook (lines 54-78 in validator.yaml) executes:

postStart:
  exec:
    command:
      - bash
      - -c
      - |
        set -eux
        VAL_INDEX=${HOSTNAME##*-}
        VAL_NAME="$(jq -r ".validators[0].name" $KEYS_CONFIG)-$VAL_INDEX"
        genesis_host="$GENESIS_HOST.$NAMESPACE.svc.cluster.local"
        until bash -e /scripts/chain-rpc-ready.sh http://$genesis_host:26657; do sleep 10; done
        $CHAIN_BIN keys show $VAL_NAME -a --keyring-backend=test | \
          bash -e /scripts/transfer-tokens.sh - $DENOM http://$genesis_host:8000/credit "true"
        bash -e /scripts/create-validator.sh

This hook:

  • Polls the genesis validator's RPC until healthy using chain-rpc-ready.sh.
  • Requests tokens from the faucet via transfer-tokens.sh if faucet.enabled is true.
  • Submits a create-validator transaction to join the active set.

Extending to Multiple Chains

To deploy a multichain topology, append additional entries to the chains list. Each chain receives its own StatefulSet and service endpoints:

chains:
  - id: osmosis-1
    name: osmosis
    numValidators: 2
    ports:
      rest: 1313
      rpc: 26653
  - id: cosmoshub-4
    name: cosmoshub
    numValidators: 1
    ports:
      rest: 1317
      rpc: 26657

Helm generates distinct resources (osmosis-validator, cosmoshub-validator) isolated by namespace and service naming conventions.

Enabling Automated Token Distribution

For validators to self-fund and join the network automatically, configure the Starship-native faucet:

faucet:
  type: starship          # Enables built-in faucet

  concurrency: 2
  resources:
    cpu: "0.1"
    memory: "200M"

The post-start hook automatically invokes transfer-tokens.sh against the faucet endpoint (http://<genesis-host>:8000/credit) before executing the validator creation script.

Summary

  • Declare topology in a single YAML file using the numValidators field to scale validator counts per chain.
  • Automate bootstrapping via init containers in templates/chains/cosmos/validator.yaml that distribute genesis files and configure P2P peers without manual SSH.
  • Deploy uniformly using starship --config <file> install, which renders Helm templates and enforces podManagementPolicy: Parallel for concurrent validator startup.
  • Fund and validate automatically through post-start hooks executing scripts/transfer-tokens.sh and scripts/create-validator.sh.
  • Scale to multichain by adding multiple entries to the chains list, with each chain receiving isolated StatefulSets and exposer services.

Frequently Asked Questions

What is the minimum number of validators required per chain?

Starship supports deploying a single validator (numValidators: 1) for development purposes. However, to test Byzantine fault tolerance or consensus mechanisms, set numValidators to 2 or higher. The framework automatically handles the genesis creation for the first replica and joins subsequent validators to the network.

How does Starship handle genesis file distribution across validators?

The genesis validator (index 0) exposes its genesis file via the sidecar exposer service on port 8081. Additional validators run an init container that executes curl to fetch the genesis from http://<genesis-host>:8081/genesis before the chain binary starts, ensuring all validators share identical initial state.

Can I mix different chain types in a single Starship deployment?

Yes. The chains list supports heterogeneous configurations. You can combine Cosmos SDK chains (configured via the cosmos validator template), Ethereum nodes, and Solana validators in the same values file. Each chain definition specifies its own name, image, and numValidators, allowing Starship to render the appropriate Kubernetes resources for each protocol.

How do I expose local ports to interact with the deployed chains?

Run make port-forward HELM_FILE=<your-config.yaml> after deployment. This executes kubectl port-forward commands for all services defined in your values file, mapping container ports (e.g., 26657 for RPC, 1317 for REST) to localhost. Alternatively, manually forward specific services using kubectl port-forward svc/<service-name> <local-port>:<target-port> -n <namespace>.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →