Auto-deploy to racknerd2 after a successful build
All checks were successful
Build & Push Images / build (push) Successful in 38s
CI / validate (push) Successful in 1m11s
Build & Push Images / deploy (push) Successful in 23s

Add a `deploy` job to build.yml that needs `build`, so every push to main
builds + pushes the images and then deploys them to racknerd2 over the
mesh, pinned to the built commit's SHA, with an /api/health gate. Fully
hands-off.

The standalone deploy.yml stays as a manual workflow_dispatch for
deploying/rolling back to an arbitrary tag without rebuilding.

deploy/README.md updated to document the auto-deploy flow.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
This commit is contained in:
Samuel James 2026-06-25 11:34:27 -04:00
parent 2b2a809352
commit bddf891c0a
2 changed files with 53 additions and 10 deletions

View file

@ -70,3 +70,37 @@ jobs:
- name: Log out
if: always()
run: docker logout "$REGISTRY"
deploy:
# Auto-deploy to racknerd2 after a successful build. Deploys the exact
# images just built (pinned to this commit's SHA). For manual/on-demand
# deploys of an arbitrary tag (e.g. rollback), use the separate
# "Deploy to racknerd2" workflow (deploy.yml).
needs: build
runs-on: docker
env:
DEPLOY_HOST: 100.96.217.250
DEPLOY_DIR: /opt/archnest
steps:
- name: Install SSH client
run: |
apt-get update
apt-get install -y --no-install-recommends openssh-client
- name: Write deploy key
run: |
install -m 700 -d ~/.ssh
printf '%s\n' "${{ secrets.RACKNERD2_SSH_KEY }}" > ~/.ssh/id_deploy
chmod 600 ~/.ssh/id_deploy
- name: Pull this build's images and restart stack
run: |
ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=accept-new \
root@"$DEPLOY_HOST" \
"cd $DEPLOY_DIR && ARCHNEST_TAG='${{ github.sha }}' docker compose pull && ARCHNEST_TAG='${{ github.sha }}' docker compose up -d --remove-orphans"
- name: Health check (backend /api/health via mesh)
run: |
ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=accept-new \
root@"$DEPLOY_HOST" \
"for i in \$(seq 1 30); do curl -fsS http://$DEPLOY_HOST:8080/api/health && echo OK && exit 0; sleep 2; done; echo 'health check failed'; cd $DEPLOY_DIR && docker compose logs --tail=50; exit 1"

View file

@ -6,11 +6,17 @@ over the NetBird mesh. racknerd2 only pulls and runs — it never builds (1.9 Gi
RAM).
```
push to main / manual ─► [build.yml] build + push images ─► registry.snsnetlabs.com/sam/{archnest,archnest-backend}
push to main ─► [build.yml]
job: build ─► build + push images ─► registry.snsnetlabs.com/sam/{archnest,archnest-backend}
job: deploy ─► (needs build) ssh racknerd2 ─► compose pull + up -d (this build's SHA) ─► /api/health
manual dispatch ─► [deploy.yml] ssh racknerd2 ─► docker compose pull && up -d
manual dispatch (any tag / rollback) ─► [deploy.yml] ssh racknerd2 ─► compose pull && up -d
```
Every push to `main` auto-builds and auto-deploys to racknerd2. `deploy.yml`
stays as a manual `workflow_dispatch` for deploying/rolling back to an arbitrary
tag without rebuilding.
## Images
| Image | From | Tags |
@ -65,16 +71,19 @@ ufw, so this is what keeps the app off the public interface. Validate at
## Running it
1. **Build**: push to `main`, or run **Build & Push Images** manually
(Actions tab → Run workflow).
2. **Deploy**: run **Deploy to racknerd2** manually, entering the tag
(`latest` or a specific commit SHA). It pulls, restarts, and health-checks
`/api/health`.
- **Automatic**: push to `main``build.yml` builds + pushes both images, then
its `deploy` job (needs `build`) pulls this commit's SHA onto racknerd2,
restarts the stack, and health-checks `/api/health`. Fully hands-off.
- **Manual build**: run **Build & Push Images** from the Actions tab (also
triggers the auto-deploy job).
- **Manual deploy / rollback**: run **Deploy to racknerd2**, entering any tag
(`latest` or a specific commit SHA) to deploy without rebuilding.
## Notes / ceilings
- `ponytail:` deploy is manual (workflow_dispatch), not auto-on-merge — this is
a validation host, so deploys are deliberate. Wire `build.yml``deploy.yml`
with `needs:` later if auto-deploy-to-validation is wanted.
- Auto-deploy targets racknerd2 (the validation host) on every push to `main`,
pinned to the built commit's SHA. If you later add a prod host, gate
prod deploys behind a manual approval or a tag/release trigger rather than
every push.
- Single-arch (amd64) only — both the runner host and racknerd2 are amd64, so
no buildx/multi-platform is needed.