0005 — GitHub Actions → GHCR → pull-based deploy¶
Status: accepted (2026-07-23)
Context¶
The repo's original scripts/ deployed by password-authenticated
rsync-and-restart (removed in 1120727); nothing was reproducible and the
VPS is too small to build images. Karat's pipeline (build in CI, pull on the
server) has been running reliably and is the obvious template.
Decision¶
Per-component workflows (.github/workflows/deploy-*.yml) build images with
Buildx (GHA layer cache), push latest + sha-<short> to
ghcr.io/aimorgcode/*, copy the deploy/ configs to /opt/aim-store, then
SSH in and run docker compose pull + up -d --no-build for just the
affected services — serialized with flock /tmp/aim-store-deploy.lock,
fail-fast, and verified by curl --resolve <domain>:443:200.141.2.84 health
checks. Backend deploys additionally take pg_dump and mongodump
backups into /opt/aim-store/backups (last 14 of each) and run
deploy/apply-migrations.sh before restarting.
Consequences¶
- The server never builds; deploys are minutes and reproducible; every deploy has a restorable pre-migration backup of both databases.
- Rollback = pin
API_IMAGE_TAG/WEBSITE_IMAGE_TAG/ADMIN_PORTAL_IMAGE_TAG/DOCS_IMAGE_TAGto a previoussha-tag and re-runup -d --no-build. - Requires two small-blast-radius credentials: an SSH deploy key
(
VPS_SSH_KEY+VPS_HOST/VPS_USER) and aread:packagespull token (GHCR_PULL_USER/GHCR_PULL_TOKEN).