Upgrade and rollback
Crumb releases are versioned images: a git tag vMAJOR.MINOR.PATCH produces
api and recorder images tagged with that version. Upgrading is a matter
of pointing .env at a newer version and pulling; rolling back is the same
in reverse.
Upgrading
cd /opt/crumb/app # or wherever your docker-compose.yml lives
# Back up first: migrations may run as part of the upgrade.
scripts/backup-db.sh
# In .env, set:
# CRUMB_IMAGE_PREFIX=ghcr.io/<owner>/crumb
# CRUMB_VERSION=v1.2.0
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=50 api recorder
Migrations are applied automatically. The api and recorder containers
each embed a migration runner that is the single source of truth for the
database schema: on every startup it applies any migration not yet marked
as applied, in order, and records it. This runs the same way on a fresh
install and on every upgrade, so a new version that ships a migration
applies it without a separate step. Still back up before upgrading, and
treat any release that calls out a non-additive migration with extra
care (see Rollback below).
If you're building from source rather than pulling images, leave
CRUMB_VERSION unset and use
docker compose up -d --build instead.
Rollback
Versioned images make rollback symmetrical with upgrade:
cd /opt/crumb/app
# In .env, set CRUMB_VERSION back to the previous tag, e.g. v1.1.0
docker compose pull
docker compose up -d
docker compose ps
The one caveat is database migrations are not automatically reversed. Rolling the container images back does not undo a schema change the now-newer version applied. In practice:
- Most migrations are additive (new nullable columns, new tables), so an older binary keeps working fine against a newer schema, and rollback is just the compose steps above.
- If a specific release's migration is genuinely breaking, rolling back means treating it as a restore: stop the services, restore the pre-upgrade database backup you took before upgrading, then bring the older version up against the restored database.
This is exactly why the upgrade steps above start with a backup, and why
keeping at least the last couple of released image versions available (not
aggressively pruning a registry) keeps rollback a one-pull operation
rather than a rebuild-from-source scramble.
Versioning
Releases follow semver: patch releases are fixes, minor releases add features without breaking compatibility, and major releases may include a breaking change, called out explicitly in the release notes when a migration isn't backward compatible.
Local and development builds
None of the above is required for day-to-day development. With
CRUMB_VERSION left unset, docker compose up -d --build builds and runs
local images from source, which is also the default before you've pinned a
published version at all.