Skip to main content
This guide covers deploying a multi-node Cowboy validator network. For a single local node, see Getting Started and the Configuration reference; this page picks up where those leave off.

1. Generate configs and genesis

All deployment configs and the genesis file are produced by the setup binary (node/validator/src/setup.rs). It has two modes under generate:
cargo run -p validator --bin setup -- generate local \
  --peers 4 --bootstrappers 1 \
  --worker-threads 4 --signature-threads 2 \
  --message-backlog 1024 --mailbox-size 1024 --deque-size 1024 \
  --log-level info --start-port 4000 \
  --output ./test
Output (written to --output):
FilePurpose
genesis.jsonGenesis state — accounts, total_supply, chain_id, network, pre-registered relay nodes
<pubkey>.yamlOne validator config per peer (consensus key + share, ports, directory)
peers.yamlPeer address map (P2P)
<address>.yamlsecp256k1 user keypairs for CLI use
config.yaml (remote only)AWS deployer config — instances, regions, monitoring
dashboard.json (remote only)Grafana dashboard, copied from --dashboard
remote adds the AWS-specific flags (--regions, --instance-type, --storage-size, --monitoring-instance-type, --monitoring-storage-size, --dashboard, and the optional --indexer-url / --indexer-count pair). EBS volumes use storage class gp3.

2. Validator configuration

Each <pubkey>.yaml is the validator’s runtime config. The fields that matter for a deployment (full list in the Configuration reference):
FieldNotes
private_key, share, polynomialConsensus signing key + BLS threshold material — secrets, back them up (see Snapshots & Restore)
portP2P consensus port
rpc_portHTTP RPC port; omit to disable RPC on this validator
metrics_portPrometheus /metrics port
directoryState / QMDB storage root — the bulk of what you back up
genesis_config_pathPath to genesis.json (relative paths resolve against the config file’s directory)
allowed_peers, bootstrappersEd25519 peer public keys; bootstrappers are the initial-contact subset
enable_faucetDefault false. Only honored on chain_id 1 (local) or 100 (dev); keep false on any real network
chain_id, networkReplay-protection + delegation-cert domain separation; inherited from genesis.json if omitted
indexerOptional indexer URL the validator pushes seeds / notarizations / finalizations to
chain_id and network are read from genesis.json at startup when not set in the YAML, so the genesis file is the single source of truth for network identity.

3. Container image

CI publishes a validator image to ghcr.io/cowboyinc/validator tagged with the branch, sha-<hash>, and the release version. Run it with the generated YAML + genesis mounted, exposing the P2P, RPC, and metrics ports. For a from-source run instead, build the release binaries (cargo build --release, producing validator, setup, indexer, cowboy, cowboy-ras-write-relayer).
The repo’s scripts/restart_validator.sh is a local-devnet helper that deletes state on restart. Never use it in production — manage the validator with systemd / your orchestrator instead. See Incident Response.

4. Deploy pipeline

The reference deploy flow lives in node/.github/workflows/pipeline.yml and promote.yml:
  1. CI gatesfmtlint → sharded test (+ a PVM simulation suite and a release-build assertion).
  2. Build Binariescargo build --release, artifacts uploaded to S3.
  3. Package image — Docker image pushed to ghcr.io/cowboyinc/validator.
  4. Deploy Dev — on main, an SSM command rolls the new binary onto the dev validator.
  5. Promote (promote.yml) — a stg-v* / prd-v* tag resolves the dev-built binary and does a rolling SSM deploy in a safe order: non-bootstrapper validators → the bootstrapper (validator-01) → RPC nodes, each node stopping its services, downloading the binary, and restarting before the next.
Promotion to staging/prod is gated on a tests-passed marker from the dev run, so only binaries that passed CI on dev are eligible.

5. Post-deploy verification

After a node starts, confirm health (see Incident Response):
curl -s http://<node>:<rpc_port>/health            # {"status":"ok"}
curl -s http://<node>:<rpc_port>/health/detailed   # height, mempool, component status
curl -s http://<node>:<metrics_port>/metrics       # Prometheus scrape
A freshly-joined node catches up via state-sync (see Snapshots & Restore); watch block_height on /health/detailed climb toward the network tip.