dev_arc_aws/deploy
Samuel James 00fc3ceed3
Some checks failed
Build & Push Images / build (push) Failing after 29s
CI / validate (push) Successful in 1m12s
Point registry at registry.snsnetlabs.com; record even=dev versioning
The Forgejo container registry now lives on a dedicated unproxied
(DNS-only) host, registry.snsnetlabs.com, so large image layers bypass
Cloudflare's ~100 MB request-body cap (the backend image's 262 MB and
317 MB layers previously hit 413 Payload Too Large through the proxied
forgejo.snsnetlabs.com host). The web UI / packages list stays on
forgejo.snsnetlabs.com behind Cloudflare Access SSO.

- build.yml: REGISTRY -> registry.snsnetlabs.com
- deploy/docker-compose.yml: image refs -> registry.snsnetlabs.com
- deploy/README.md: push/pull/login host -> registry.snsnetlabs.com
  (packages web UI URL kept on forgejo.snsnetlabs.com)

Also record the versioning convention in HANDOFF + steering: development
happens on even major versions, releases on odd; currently developing v2
(prior released line is v1, see the v1.0 git tag). package.json and the
About panel are not yet bumped to v2.

Validated end to end: built both images on the runner host, pushed to
registry.snsnetlabs.com (backend included, no 413), pulled on racknerd2,
brought the stack up, /api/health returns {"ok":true} over the mesh IP.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-25 10:55:15 -04:00
..
.env.example Add Forgejo Actions build + deploy pipeline (registry -> racknerd2) 2026-06-25 10:04:59 -04:00
docker-compose.yml Point registry at registry.snsnetlabs.com; record even=dev versioning 2026-06-25 10:55:15 -04:00
README.md Point registry at registry.snsnetlabs.com; record even=dev versioning 2026-06-25 10:55:15 -04:00

ArchNest — Build & Deploy (Forgejo Actions → registry → racknerd2)

This pipeline builds the Docker images in Forgejo Actions, pushes them to the Forgejo container registry, and deploys them to racknerd2 (validation host) over the NetBird mesh. racknerd2 only pulls and runs — it never builds (1.9 GiB RAM).

push to main / manual ─► [build.yml] build + push images ─► registry.snsnetlabs.com/sam/{archnest,archnest-backend}
                                                                      │
                                          manual dispatch ─► [deploy.yml] ssh racknerd2 ─► docker compose pull && up -d

Images

Image From Tags
registry.snsnetlabs.com/sam/archnest root Dockerfile (React build → nginx) latest, <commit-sha>
registry.snsnetlabs.com/sam/archnest-backend backend/Dockerfile (Fastify) latest, <commit-sha>

registry.snsnetlabs.com is the unproxied (DNS-only) registry host, so large layers bypass Cloudflare's ~100 MB request-body cap. Pushed images appear at https://forgejo.snsnetlabs.com/sam/-/packages (web UI, Cloudflare Access SSO).

One-time setup

1. Forgejo Actions secrets (repo or org settings → Actions → Secrets)

  • FORGEJO_REGISTRY_TOKEN — Forgejo personal access token for sam with package scope (NOT the account password). Used by build.yml to log in and push.
  • RACKNERD2_SSH_KEY — private SSH key authorized for root@racknerd2 (mesh IP 100.96.217.250). Used by deploy.yml.

2. Runner (forgejo-runner host) — allow Docker builds

The runner runs jobs inside containers and by default has no Docker access. Enable socket auto-mounting so the build job can build images. Create /opt/config.yaml (or edit the existing runner config) with at least:

container:
  docker_host: "automount"   # mounts /var/run/docker.sock into job containers

Generate a full example with forgejo-runner generate-config > /opt/config.yaml, set docker_host: "automount", point the service at it (ExecStart=/usr/local/bin/forgejo-runner daemon -c /opt/config.yaml), then systemctl daemon-reload && systemctl restart forgejo-runner.

3. racknerd2 — prepare the deploy host

Docker Engine + compose plugin are already installed. Then:

mkdir -p /opt/archnest
# copy deploy/docker-compose.yml from this repo to /opt/archnest/docker-compose.yml
# create /opt/archnest/.env from deploy/.env.example and fill in the secrets:
#   ARCHNEST_JWT_SECRET   = openssl rand -hex 32
#   ARCHNEST_SECRET_KEY   = openssl rand -hex 32
#   ARCHNEST_GUAC_CRYPT_KEY = openssl rand -base64 24 | cut -c1-32
docker login registry.snsnetlabs.com   # user: sam, password: the package token

Ports are bound to the mesh IP only (100.96.217.250) — Docker bypasses ufw, so this is what keeps the app off the public interface. Validate at http://100.96.217.250:8080.

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.

Notes / ceilings

  • ponytail: deploy is manual (workflow_dispatch), not auto-on-merge — this is a validation host, so deploys are deliberate. Wire build.ymldeploy.yml with needs: later if auto-deploy-to-validation is wanted.
  • Single-arch (amd64) only — both the runner host and racknerd2 are amd64, so no buildx/multi-platform is needed.