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 attemplates/chains/cosmos/validator.yamlcontains the logic that createsreplicas = numValidators-1additional 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--configflag and orchestrates Helm commands. The entry point is defined incmd/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:
- Initializes the chain home directory with
chaind init. - Generates the genesis file and stores it in a shared location.
- 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.jsonConfigMap using the validator index. - Fetches the genesis file from the genesis validator's exposer.
- Configures
persistent_peersinconfig.tomlto 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.shiffaucet.enabledis true. - Submits a
create-validatortransaction 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
numValidatorsfield to scale validator counts per chain. - Automate bootstrapping via init containers in
templates/chains/cosmos/validator.yamlthat distribute genesis files and configure P2P peers without manual SSH. - Deploy uniformly using
starship --config <file> install, which renders Helm templates and enforcespodManagementPolicy: Parallelfor concurrent validator startup. - Fund and validate automatically through post-start hooks executing
scripts/transfer-tokens.shandscripts/create-validator.sh. - Scale to multichain by adding multiple entries to the
chainslist, 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →