Upgrades.

Sudo treats a release as a single atomic thing: pinned Docker image tags, a voice-loop git ref, a config-schema version, and migration IDs. Either the whole release is applied and verified, or the Pi is rolled back to the previous known-good state. No half-upgraded hosts.

The release manifest

Every release is described by a JSON entry like this:

json
{
  "version": "0.2.0",
  "releasedAt": "2026-05-12",
  "configSchemaVersion": 2,
  "voiceLoopGitRef": "v0.2.0",
  "composeImageTags": {
    "homeassistant": "ghcr.io/home-assistant/home-assistant:2026.5",
    "whisper": "rhasspy/wyoming-whisper:1.6.1",
    "piper": "rhasspy/wyoming-piper:1.5.0",
    "openwakeword": "rhasspy/wyoming-openwakeword:1.10.0",
    "mosquitto": "eclipse-mosquitto:2.0.20"
  },
  "migrationIds": ["001-rename-stt"],
  "notes": "Whisper 1.6, new wake-word model format."
}

The manifest lives in-repo at onboarding/releases/manifest.json and is fetched from your server when the Ready screen checks for updates.

Deployment is verification

When you click Upgrade from the Ready screen, Sudo runs this sequence:

  1. Snapshot. Copies .env, docker-compose.yml, voice-loop/config.yaml, and the MCP config into onboarding/data/backups/<timestamp>/.
  2. Migrate config. Runs any migrations listed in migrationIds against the in-memory bundle — e.g. renaming a YAML key, moving a field, or seeding a default.
  3. Pull & restart. docker compose pull, then down, then up -d.
  4. Verify. Runs make test-ha and make smoke-mcp with a 90s budget. This is the verification — there is no separate QA step.
  5. Commit or roll back. On success, writes the new version to onboarding/data/release.json. On failure, restores the snapshot and brings services back up.

Rollback

Rollback is automatic on verification failure, but you can also trigger it manually. Snapshots are kept indefinitely under onboarding/data/backups/:

bash
cd ~/sudo
ls onboarding/data/backups/
# 2026-04-21T10-15-00-000Z/
# 2026-04-28T14-02-11-112Z/

# To manually restore a snapshot:
cp onboarding/data/backups/<ts>/env ./.env
cp onboarding/data/backups/<ts>/docker-compose.yml ./docker-compose.yml
cp onboarding/data/backups/<ts>/voice-loop-config.yaml ./voice-loop/config.yaml
make down && make up

Self-hosting upgrades

If you host the Sudo tarball on your own Caddy (see Install), you own the upgrade channel. Your Pis check the manifest at SUDO_RELEASE_MANIFEST_URL (defaults to the baked-in URL; override via systemd environment if you want your own):

bash
# /etc/systemd/system/sudo-onboarding.service.d/override.conf
[Service]
Environment=SUDO_RELEASE_MANIFEST_URL=https://sudo.example.net/manifest.json

What's NOT in v0.1

  • Image-tag rewriting on upgrade. The upgrade flow runs docker compose pull against the existing docker-compose.yml. Tag changes across releases require extending lib/release/upgrade.ts to render a new compose file from composeImageTags.
  • HA version gating. supportedHaVersions is in the manifest schema but not enforced yet.