# How Starship Automates Blockchain Upgrades with Cosmovisor

> Discover how Starship automates Cosmos SDK blockchain upgrades with Cosmovisor for zero downtime. Learn how to embed Cosmovisor into validator containers for seamless binary switches.

- Repository: [Hyperweb/starship](https://github.com/hyperweb-io/starship)
- Tags: how-to-guide
- Published: 2026-03-03

---

**Starship automates Cosmos SDK blockchain upgrades by embedding Cosmovisor into validator containers, pre-building genesis and upgrade binaries, and enabling zero-downtime binary switches at scheduled block heights without manual pod restarts.**

Starship, developed by **hyperweb-io/starship**, eliminates manual intervention during blockchain upgrades by integrating Cosmovisor directly into its Kubernetes-native infrastructure. This automation allows Cosmos SDK chains to transition between protocol versions seamlessly through governance proposals, handling binary compilation, distribution, and execution within the container orchestration layer.

## Understanding the Starship Upgrade Architecture

Starship’s upgrade mechanism operates through three tightly coupled layers: configuration management, binary preparation, and runtime orchestration. Each layer maps to specific source files in the repository that handle distinct responsibilities in the upgrade lifecycle.

### Configuration Layer: The Upgrade Struct

User-defined upgrade parameters are unmarshalled into the `Upgrade` struct defined in [`starship/cmd/starship/model.go`](https://github.com/hyperweb-io/starship/blob/main/starship/cmd/starship/model.go). This struct captures the genesis version and future upgrade paths specified in Helm values.

The configuration requires `upgrade.enabled: true` alongside specific version tags:

```yaml
upgrade:
  enabled: true
  genesis: v7.0.0
  upgrades:
    - name: v8.0.0
      version: v8.0.0
    - name: v9.0.0
      version: v9.0.0

```

When the generator processes this configuration, it triggers the `CosmosValidatorStatefulSetGenerator` to inject additional init containers into the validator StatefulSet manifest.

### Build and Installation Process

The `CosmosValidatorStatefulSetGenerator` (located in [`packages/generator/src/builders/chains/cosmos/validator.ts`](https://github.com/hyperweb-io/starship/blob/main/packages/generator/src/builders/chains/cosmos/validator.ts)) programmatically adds an `init-build-images` container when `chain.upgrade.enabled` evaluates to true. This container handles two critical tasks:

1. **Cosmovisor Installation**: Executes `go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0` to place the binary in the container’s `$GOBIN`.

2. **Binary Compilation**: Iterates through the upgrade list, invoking [`build-chain.sh`](https://github.com/hyperweb-io/starship/blob/main/build-chain.sh) with `UPGRADE_NAME` and `CODE_TAG` environment variables for each version.

The [`build-chain.sh`](https://github.com/hyperweb-io/starship/blob/main/build-chain.sh) script (found in [`charts/devnet/scripts/default/build-chain.sh`](https://github.com/hyperweb-io/starship/blob/main/charts/devnet/scripts/default/build-chain.sh)) checks out the specified source code tags, compiles binaries using `make install`, and organizes them into Cosmovisor’s expected directory hierarchy:

```bash
if [[ $UPGRADE_NAME == "genesis" ]]; then
  mkdir -p $UPGRADE_DIR/genesis/bin
  cp $GOBIN/$CHAIN_BIN $UPGRADE_DIR/genesis/bin
else
  mkdir -p $UPGRADE_DIR/upgrades/$UPGRADE_NAME/bin
  cp $GOBIN/$CHAIN_BIN $UPGRADE_DIR/upgrades/$UPGRADE_NAME/bin
fi

```

### Runtime Execution and Binary Switching

The validator pod defined in [`charts/devnet/templates/chains/cosmos/validator.yaml`](https://github.com/hyperweb-io/starship/blob/main/charts/devnet/templates/chains/cosmos/validator.yaml) uses specialized init containers to prepare the runtime environment. The `init-validator` and `init-config` containers copy the genesis binary from `$CHAIN_DIR/cosmovisor/genesis/bin/$CHAIN_BIN` to `/usr/bin`, establishing Cosmovisor as the entry point.

When a governance proposal triggers an on-chain upgrade at a specific block height, Cosmovisor detects the matching directory under `$UPGRADE_DIR/upgrades/<upgrade-name>/bin`, swaps the active binary, and restarts the process automatically. This occurs without pod recreation or manual intervention, as demonstrated in the upgrade test suite.

## Step-by-Step Implementation Guide

Implementing automated upgrades requires configuring the Helm values, ensuring proper binary placement, and submitting governance proposals.

### 1. Enable Upgrades in Helm Configuration

Define the upgrade path in your [`values.yaml`](https://github.com/hyperweb-io/starship/blob/main/values.yaml) by specifying the genesis version and all subsequent upgrades:

```yaml
chains:
  - id: persistencecore
    name: persistencecore
    image: ghcr.io/cosmology-tech/persistencecore:latest
    upgrade:
      enabled: true
      genesis: v7.0.0
      upgrades:
        - name: v8.0.0
          version: v8.0.0
        - name: v9.0.0
          version: v9.0.0

```

### 2. Verify Init Container Generation

Starship generates the `init-build-images` container automatically. The generated manifest includes commands to build each binary version:

```yaml
initContainers:
  - name: init-build-images
    image: ghcr.io/cosmology-tech/starship/builder:latest
    command:
      - bash
      - -c
      - |
        go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0
        UPGRADE_NAME=genesis CODE_TAG=v7.0.0 bash -e /scripts/build-chain.sh
        UPGRADE_NAME=v8.0.0 CODE_TAG=v8.0.0 bash -e /scripts/build-chain.sh

```

### 3. Submit Governance Proposal

Use the chain’s governance module to schedule the upgrade. The test in [`examples/upgrade-test/upgrade_test.go`](https://github.com/hyperweb-io/starship/blob/main/examples/upgrade-test/upgrade_test.go) demonstrates the complete flow:

```go
plan := upgradetypes.Plan{
    Name:   "v8.0.0",
    Height: upgradeHeight,
}
msg := &gov.MsgSubmitProposal{}
msg.SetContent(upgradetypes.NewSoftwareUpgradeProposal(
    "Software upgrade",
    "software upgrade",
    plan,
))
res, err := chain.SendMsg(ctx, msg, "Software upgrade proposal")

```

### 4. Monitor Upgrade Execution

Wait for the chain to reach the specified upgrade height, then verify the upgrade applied successfully:

```go
s.WaitForHeight(chain, upgradeHeight+1)
upgradeClient := upgradetypes.NewQueryClient(chain.Client)
planRes, _ := upgradeClient.AppliedPlan(ctx, &upgradetypes.QueryAppliedPlanRequest{Name: "v8.0.0"})

```

At the target height, Cosmovisor automatically switches to the new binary located in `$UPGRADE_DIR/upgrades/v8.0.0/bin/`.

## Code Examples for Production Use

### Validator Init Container Configuration

The validator template handles binary placement through conditional copy operations:

```yaml
- name: init-validator
  image: {{ $chain.image }}
  command:
    - bash
    - -c
    - |
      if [[ -f $CHAIN_DIR/cosmovisor/genesis/bin/$CHAIN_BIN ]]; then
        cp $CHAIN_DIR/cosmovisor/genesis/bin/$CHAIN_BIN /usr/bin
      fi
      # Additional validator initialization...

```

### Complete Upgrade Test Workflow

This Go test validates the end-to-end upgrade process, including proposal submission and state verification:

```go
package upgradetest

import (
    upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
    gov "github.com/cosmos/cosmos-sdk/x/gov/types"
)

func TestSoftwareUpgrade(t *testing.T) {
    plan := upgradetypes.Plan{
        Name:   "v8.0.0",
        Height: 100,
    }
    
    msg := &gov.MsgSubmitProposal{}
    msg.SetContent(upgradetypes.NewSoftwareUpgradeProposal(
        "Software upgrade",
        "Upgrade to v8.0.0",
        plan,
    ))
    
    res, err := chain.SendMsg(ctx, msg)
    require.NoError(t, err)
    
    // Wait for upgrade height
    s.WaitForHeight(chain, 101)
    
    // Verify upgrade applied
    client := upgradetypes.NewQueryClient(chain.Client)
    applied, _ := client.AppliedPlan(ctx, &upgradetypes.QueryAppliedPlanRequest{Name: "v8.0.0"})
    require.Equal(t, int64(100), applied.Height)
}

```

## Summary

- **Configuration-driven upgrades**: The `Upgrade` struct in [`starship/cmd/starship/model.go`](https://github.com/hyperweb-io/starship/blob/main/starship/cmd/starship/model.go) parses Helm values to define genesis and future binary versions.
- **Automated binary preparation**: The `CosmosValidatorStatefulSetGenerator` injects `init-build-images` containers that execute [`build-chain.sh`](https://github.com/hyperweb-io/starship/blob/main/build-chain.sh) to compile and organize binaries in Cosmovisor’s directory structure.
- **Zero-downtime execution**: Cosmovisor manages binary switching at the scheduled block height without requiring pod restarts or manual intervention, as implemented in [`charts/devnet/templates/chains/cosmos/validator.yaml`](https://github.com/hyperweb-io/starship/blob/main/charts/devnet/templates/chains/cosmos/validator.yaml).
- **Governance integration**: Upgrade proposals submitted through the SDK’s `upgrade` module trigger automatic binary swaps when the specified height is reached.

## Frequently Asked Questions

### What version of Cosmovisor does Starship install?

Starship installs **Cosmovisor v1.0.0** by default, as specified in the `init-build-images` container command (`go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0`). You can modify this version in the generator code at [`packages/generator/src/builders/chains/cosmos/validator.ts`](https://github.com/hyperweb-io/starship/blob/main/packages/generator/src/builders/chains/cosmos/validator.ts) if your chain requires a specific Cosmovisor release.

### How does Starship handle binary storage for multiple upgrade versions?

Starship organizes binaries using Cosmovisor’s standard directory layout. The [`build-chain.sh`](https://github.com/hyperweb-io/starship/blob/main/build-chain.sh) script places the genesis binary in `$UPGRADE_DIR/genesis/bin/` and subsequent upgrade binaries in `$UPGRADE_DIR/upgrades/<name>/bin/`. This structure allows Cosmovisor to locate and switch binaries automatically when upgrade heights are reached.

### Can I perform upgrades without restarting the validator pods?

Yes. Starship’s architecture eliminates the need for manual pod restarts. Once the `init-build-images` container completes the initial binary setup, Cosmovisor manages the runtime process. When an upgrade proposal executes at the specified block height, Cosmovisor swaps the binary and restarts the process internally within the same pod, maintaining chain continuity.

### Where is the Cosmovisor binary located in the runtime container?

The Cosmovisor binary resides in the Starship runner image defined in `docker/starship/runner/Dockerfile`. This image serves as the base for validator containers, ensuring Cosmovisor is available at runtime to manage the chain binary lifecycle. The genesis binary is copied to `/usr/bin` during initialization to serve as Cosmovisor’s launch target.