feat(deploy): publish image to Gitea Packages + switch netcup to image pull #42

Open
libretech wants to merge 4 commits from feat/registry-deploy into main
Owner

Closes #39.

Summary

  • compose.netcup.yaml no longer builds locally; pulls ${LIBRENOTES_IMAGE} (default git.librete.ch/public/librenotes:main).
  • .gitea/workflows/deploy.yml builds + pushes to ${REGISTRY}/public/librenotes (main → :main + :<sha7>; tag → :vX.Y.Z + :latest), then SSHes to the deploy host and reruns compose. Tag pushes pin LIBRENOTES_IMAGE in the host .env via perl -i.
  • Both workflow jobs (and ci.yml) run inside catthehacker/ubuntu:runner-latest because the default node:20-bookworm runner image lacks make and a docker CLI. The build job bind-mounts /var/run/docker.sock; the runner repo's config.yaml whitelists that path under valid_volumes.
  • Renamed docker-compose.{yml,prod.yml}compose.{yaml,prod.yaml} (Compose v2 spec).
  • docs/operations.md + docs/self-hosting.md updated with the new secret matrix, compose invocations, rollback example, and Gitea runner notes.

Out-of-band tasks (left for the operator)

  • Create a Gitea robot account or PAT with package:write on the public org.
  • Set repo secrets at https://git.librete.ch/public/librenotes/settings/actions/secrets:
    REGISTRY=git.librete.ch, REGISTRY_USER, REGISTRY_PASS,
    DEPLOY_HOST=root@netcup, DEPLOY_KEY (passphrase-less private key),
    DEPLOY_PATH=/srv/librenotes,
    HEALTH_URL=https://ln.cloud.librete.ch/healthz.
  • Set repo variable DEPLOY_ENABLED=true.
  • Restart the netcup runner so the new valid_volumes entry is loaded.
  • On netcup /srv/librenotes/.env, add LIBRENOTES_IMAGE=git.librete.ch/public/librenotes:v0.1.0.

Verification

  • yq -e . parses all touched YAML.
  • docker compose -f compose.yaml -f compose.netcup.yaml config resolves.
  • A main push will only run anything once DEPLOY_ENABLED=true; the workflow is safe to merge before secrets are set.
Closes #39. ## Summary - `compose.netcup.yaml` no longer builds locally; pulls `${LIBRENOTES_IMAGE}` (default `git.librete.ch/public/librenotes:main`). - `.gitea/workflows/deploy.yml` builds + pushes to `${REGISTRY}/public/librenotes` (main → `:main` + `:<sha7>`; tag → `:vX.Y.Z` + `:latest`), then SSHes to the deploy host and reruns compose. Tag pushes pin `LIBRENOTES_IMAGE` in the host `.env` via `perl -i`. - Both workflow jobs (and `ci.yml`) run inside `catthehacker/ubuntu:runner-latest` because the default `node:20-bookworm` runner image lacks `make` and a docker CLI. The build job bind-mounts `/var/run/docker.sock`; the runner repo's `config.yaml` whitelists that path under `valid_volumes`. - Renamed `docker-compose.{yml,prod.yml}` → `compose.{yaml,prod.yaml}` (Compose v2 spec). - `docs/operations.md` + `docs/self-hosting.md` updated with the new secret matrix, compose invocations, rollback example, and Gitea runner notes. ## Out-of-band tasks (left for the operator) - [ ] Create a Gitea robot account or PAT with `package:write` on the `public` org. - [ ] Set repo secrets at `https://git.librete.ch/public/librenotes/settings/actions/secrets`: `REGISTRY=git.librete.ch`, `REGISTRY_USER`, `REGISTRY_PASS`, `DEPLOY_HOST=root@netcup`, `DEPLOY_KEY` (passphrase-less private key), `DEPLOY_PATH=/srv/librenotes`, `HEALTH_URL=https://ln.cloud.librete.ch/healthz`. - [ ] Set repo variable `DEPLOY_ENABLED=true`. - [ ] Restart the netcup runner so the new `valid_volumes` entry is loaded. - [ ] On netcup `/srv/librenotes/.env`, add `LIBRENOTES_IMAGE=git.librete.ch/public/librenotes:v0.1.0`. ## Verification - `yq -e .` parses all touched YAML. - `docker compose -f compose.yaml -f compose.netcup.yaml config` resolves. - A `main` push will only run anything once `DEPLOY_ENABLED=true`; the workflow is safe to merge before secrets are set.
libretech added 4 commits 2026-04-29 02:06:50 +02:00
compose.netcup.yaml now references ${LIBRENOTES_IMAGE} with pull_policy: always
and resets the base build context. .env.netcup.example documents the new
LIBRENOTES_IMAGE key (default git.librete.ch/public/librenotes:main, pin to
immutable tag for prod). Rollback: edit .env LIBRENOTES_IMAGE + up -d.
- Image base is now ${REGISTRY}/public/librenotes (matches Gitea owner/repo).
- Remote step writes LIBRENOTES_IMAGE on tag pushes via perl, then pulls and
  restarts using the new compose.yaml + compose.netcup.yaml stack files.
- Both jobs run inside catthehacker/ubuntu:runner-latest; the default
  node:20-bookworm runner image lacks make + docker. The build job
  bind-mounts /var/run/docker.sock for build-push-action; the runner config
  must whitelist that path under valid_volumes.
docs(ops): document registry secrets, rollback, Gitea runner image
All checks were successful
CI / ci (pull_request) Successful in 11m39s
c261a23da8
operations.md lists the full secret/variable matrix the deploy workflow
expects, the new compose.yaml + compose.netcup.yaml invocation, and a
note on why both workflow jobs pin catthehacker/ubuntu:runner-latest.
self-hosting.md updates the example LIBRENOTES_IMAGE value to the Gitea
Packages path and switches the quick-start to compose.netcup.yaml.
All checks were successful
CI / ci (pull_request) Successful in 11m39s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/registry-deploy:feat/registry-deploy
git checkout feat/registry-deploy
Sign in to join this conversation.
No description provided.