# homelab-infra Shared CI/CD templates, base Dockerfiles, and compose snippets for all homelab projects. Change once here, every project picks it up. ## Repo structure ``` .gitea/workflows/ build-and-push.yml ← reusable workflow (called by project repos) base-images/ python-git-ssh/ Dockerfile ← Python 3.12 + git + openssh (build once) entrypoints/ git-pull-exec.sh ← pull-before-exec entrypoint for live code updates compose-snippets/ watchtower.yml ← auto-pull on image update act_runner.yml ← Gitea Actions self-hosted runner (deploy on Pi) ``` ## How a project uses the shared workflow In your project repo, create `.gitea/workflows/build.yml`: ```yaml name: Build on: push: branches: [main] workflow_dispatch: jobs: build: uses: thethreemagi/homelab-infra/.gitea/workflows/build-and-push.yml@main with: image_name: your-project-name secrets: REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} ``` Add two secrets to the project repo (Gitea → repo → Settings → Secrets): - `REGISTRY_USER` — your Gitea username (`thethreemagi`) - `REGISTRY_TOKEN` — a PAT with `write:packages` scope On push to `main`, the workflow builds a multi-tag image and pushes to `git.thewichersfamily.com/thethreemagi/your-project-name:latest`. ## One-time server setup (Gitea + runner) ### 1. Enable Actions in Gitea Edit your Gitea `app.ini` (check your Gitea compose volume mount for the path): ```ini [actions] ENABLED = true ``` Restart Gitea: `docker compose restart gitea` ### 2. Generate runner registration token Gitea → Site Administration → Actions → Runners → Create Runner → copy token. ### 3. Deploy act_runner on Pi 5 Copy `compose-snippets/act_runner.yml` to `/srv/act-runner/docker-compose.yml`. Add to `.env`: ``` RUNNER_TOKEN= ``` ```bash docker compose up -d ``` Verify: Gitea → Site Administration → Actions → Runners → `homelab-pi5` online. ### 4. Generate registry PATs **Runner PAT** (push images): - Gitea → Settings → Applications → Generate Token → scope: `write:packages` - Set as `REGISTRY_TOKEN` secret in each project repo **Pi pull PAT** (Watchtower pulls): - Gitea → Settings → Applications → Generate Token → scope: `read:packages` - On Pi: `docker login git.thewichersfamily.com` ### 5. Deploy Watchtower on Pi Use `compose-snippets/watchtower.yml`. Polls every 5 min, restarts containers on new image digest. ## Adding a new project 1. Ask Claude to create the repo via MCP (needs `write:user` scope on token) 2. Claude adds `.gitea/workflows/build.yml` calling this shared workflow 3. Add `REGISTRY_USER` + `REGISTRY_TOKEN` secrets to repo 4. Update project `docker-compose.yml`: `image: git.thewichersfamily.com/thethreemagi/:latest` 5. Push — CI runs automatically ## Runner note: ARM64 vs x86 Runner runs on Pi 5 — native ARM64 builds, no QEMU needed. If moved to x86 NAS later, uncomment the QEMU steps in `build-and-push.yml`. ## Requires Gitea 1.21+ Reusable workflows require Gitea 1.21+. Check: Site Administration → Configuration → Gitea Version.