Fix deploy pipeline checkout: no Node on host runner, repo is private

actions/checkout@v4 failed with "Cannot find: node in PATH" (the
runner intentionally has no Node toolchain). Replaced with a plain
git clone authenticated via a new DEPLOY_TOKEN Gitea Actions secret,
since the repo needs auth even for a read-only clone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 18:18:44 +02:00
parent 8733175f64
commit 6b7d47fa4c
2 changed files with 42 additions and 20 deletions
+29 -17
View File
@@ -66,24 +66,36 @@ Follow-ups (not yet done — all need you, not more code):
- [ ] Your call, no rush: encrypt `credentials.secret` at rest (e.g. pgcrypto) instead of
plaintext if the dashboard is ever exposed more broadly than Caddy basic-auth + host security.
## Deploy pipeline — trigger from the Gitea UI
## Deploy pipeline — trigger from the Gitea UI — DONE 2026-07-15 (backoffice only)
**Goal:** stop hand-running scp/ssh/docker-compose-build for every change (that's how the
credentials feature above shipped). `git.mivanchenko.de` (Gitea, already the `origin` remote for
every repo here, running alongside the other homelab containers) supports **Gitea Actions**
workflows in `.gitea/workflows/` that run on a self-hosted runner and can be started with a
manual "Run workflow" button in the repo UI, not just on push.
- [ ] Register a Gitea Actions runner (can run directly on the homelab host, or in its own
container with the Docker socket mounted so it can `docker compose build`/`up -d`).
- [ ] `.gitea/workflows/deploy.yml`: `workflow_dispatch` trigger (the UI button), optionally also
on push to `main`. Steps: checkout → sync changed paths to `/home/mivanchenko/smb-crm/` (and
whichever other `deploy/*` groups changed) → apply any pending SQL migrations → `docker compose
build` + `up -d --no-deps <service>` for just the affected Compose group(s) → hit `/healthz`
(or the equivalent) to confirm before declaring success.
- [ ] Needs real secrets in Gitea's repo/runner secrets store (SSH deploy key or a runner already
on the host, `CRM_API_TOKEN`, etc.) — **your call** on which, since it's a homelab access
decision.
- [ ] Once trustworthy, this replaces the manual migration step described in the credentials
section above and the `new-client.sh` → scp → ssh flow in `deploy/clients/README.md`.
credentials feature above originally shipped). Gitea Actions is now enabled on
`git.mivanchenko.de`, with a self-hosted runner (`homelab-runner`, labels `self-hosted`/
`homelab`) running natively on the homelab host as the `act-runner` systemd service (survives
reboots). `.gitea/workflows/deploy-backoffice.yml` is a `workflow_dispatch`-only job (manual
"Run workflow" button — deliberately not on push, since triggering it = deploying) that syncs
`backoffice/db` + `backoffice/app`, re-applies the idempotent schema, rebuilds/restarts
`smb-crm`, and health-checks it.
- [x] Runner registered — runs directly on the host with the same `docker`/filesystem access the
operator already has, so no SSH deploy key was needed for the runner itself.
- [x] Fixed along the way: the runner-token generator needs `docker exec -u git gitea …` (Gitea
refuses to run as root, `docker exec` defaults to root); the runner is registered against
Gitea's internal container IP (`http://172.24.0.2:3000`), not `git.mivanchenko.de`, because the
homelab can't reach its own public hostname (NAT hairpin) — `https://git.mivanchenko.de` calls
from the host itself just hang.
- [x] First real run failed twice, both fixed: (1) `actions/checkout@v4` needs Node.js, which the
intentionally-minimal host-mode runner doesn't have — replaced with a plain `git clone`;
(2) the repo is private, so that clone needs auth — added a `DEPLOY_TOKEN` Gitea Actions secret
(a `read:repository,write:repository`-scoped token under the admin account, stored only in
Gitea's encrypted secret store, stripped from the cloned workspace's `git remote` right after
checkout).
- [ ] **Needs you:** actually press "Run workflow" once in the Gitea UI (Actions tab →
Deploy backoffice (smb-crm)) as the real end-to-end test — I deliberately didn't mint a Gitea
API token to test-trigger it myself (that would've left a stray write-scoped credential behind).
- [ ] Extend the same pattern to the other `deploy/*` groups (`booking/`, `smb-demos/`,
`clients/<slug>/`) — straightforward once the backoffice one is confirmed working, since
they're all simpler (mostly just `docker compose up -d`, no DB migration step).
- [ ] Once you're adding collaborators: anyone with **write** access to this repo can trigger a
deploy. Worth being deliberate about who gets write vs. read/PR-only access — **your call**.
## Other
- [ ] Harden n8n auth: compose still has deprecated `N8N_BASIC_AUTH_*` with password `password`