Commit Graph
9 Commits
Author SHA1 Message Date
libretech d34df180fd fix(ci): correct image digest separator (@ not :)
CI / ci (pull_request) Successful in 14m48s
2026-04-30 12:20:19 +02:00
libretech c9470d199f ci: digest-pin runner-image v0.1.0 (was :v2)
CI / ci (pull_request) Failing after 0s
Drops the ad-hoc :vN tag scheme — see runner-image#semver. Consumers
now reference tag + digest so the resolved image is byte-identical
across runs.
2026-04-30 12:17:34 +02:00
libretech 6dd20cc9bd ci: update runner-image path to public/ namespace
CI / ci (pull_request) Failing after 1s
The runner-image repo moved from libretech/ to public/ on Gitea;
ci.yml and deploy.yml + docs reference public/runner-image.
2026-04-30 11:53:41 +02:00
libretech ecd0ae69da ci: pin runner-image v2 (adds gcc for cgo, fixes go test -race)
v1 lacked gcc, so 'go test -race' (in Makefile) failed in CI with
'go: -race requires cgo'. v2 of the runner image installs gcc,
libc6-dev, and pkg-config.
2026-04-30 00:17:05 +02:00
libretech 4ba7572565 ci(deploy): switch to libretech/runner-image:v1 and consolidate
CI / ci (pull_request) Failing after 5m52s
The deploy workflow is now a single job that builds, pushes, and
deploys in one runner. Tag computation moved to docker/metadata-action,
the per-deploy .env perl rewrite is gone (host pins LIBRENOTES_IMAGE
once; main pushes update :main rolling, releases pin to :vX.Y.Z by
manual edit), and both jobs run in our bespoke runner image whose
runner user already has socket access via group membership.

ci.yml moves to the same image so go/make/node are all available
without per-step apt installs.

Drops compose.prod.yaml (unused, redundant with compose.netcup.yaml).
2026-04-29 12:44:39 +02:00
libretech 6075aa22e1 fix(ci): drop docker.sock workflow mount (runner auto-mounts it)
Deploy / build (push) Failing after 2m18s
Deploy / deploy (push) Has been skipped
CI / ci (push) Successful in 11m11s
The Gitea act_runner already bind-mounts /var/run/docker.sock into job
containers when its own runner container has the socket mounted. The
workflow-level mount duplicated it and act_runner aborted the job with
'Duplicate mount point: /var/run/docker.sock'.
2026-04-29 12:17:25 +02:00
libretech 3d3fc41f73 ci(deploy): always pin LIBRENOTES_IMAGE and git pull on remote
CI / ci (pull_request) Successful in 12m34s
First deploy now works without manual .env priming: the remote step
unconditionally rewrites LIBRENOTES_IMAGE, then runs git pull --ff-only
so the host picks up the renamed compose.* files before pull/up.
2026-04-29 11:46:21 +02:00
libretech 37842b6294 ci(deploy): fix registry path, compose refs, Gitea Actions compat
- 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.
2026-04-29 02:00:23 +02:00
libretechandClaude Opus 4.7 bcccba92f7 Add deploy workflow and backup tooling
CI deployment (.gitea/workflows/deploy.yml):
- Two jobs (build, deploy) gated on the repo variable
  DEPLOY_ENABLED=true so the workflow exists but does nothing
  until secrets and host are configured.
- Build pushes two image tags per run: rolling :main + the short
  SHA on main, or vX.Y.Z + :latest on tag pushes. Immutable per
  commit/tag tags make rollback trivial.
- Deploy SSHes to DEPLOY_HOST, runs docker compose pull && up -d
  in DEPLOY_PATH, then polls HEALTH_URL for up to a minute. A
  failed health check fails the workflow, which is the alert.
- Required secrets and the rollback procedure are documented in
  docs/operations.md.

Backup tooling (scripts/):
- backup.sh: SQLite online .backup snapshot + tarball of the
  per-tenant data dir + info.txt header, all wrapped into a
  single librenotes-YYYYMMDD-HHMMSS.tar.gz. Optional BACKUP_REMOTE
  triggers an rclone copy for off-site storage.
- backup-prune.sh: enforces retention "30 daily + 12 monthly".
  Sorts archives by filename (date is in the name so lex order
  matches chronological) and keeps the newest 30 plus the newest
  archive for each of the most recent 12 months.
- backup-restore-test.sh: extracts the most recent archive into
  a tmpdir, runs sqlite3 .schema (proves DB readability), and
  asserts the notes tar has at least one entry. Failure is the
  alert. Wired into a separate weekly timer.
- librenotes-backup.{service,timer}: systemd units for the daily
  03:17 UTC run with 5min jitter; ProtectSystem=strict, only
  /var/backups/librenotes is writable.
- librenotes-backup-verify.{service,timer}: weekly Monday
  04:00 UTC restore test.

Closes #26 and #27.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:49:40 +02:00