Commit f2bffdcbb5

f2bffdcbb58d25feff7df76cef83edf96df69e40

parent: cae1d071e4

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-02 02:56 UTC

Admin: runners, healthz, monitor backup ages, gc --lfs, backup --verify

Ref krz/gitbay#75 #76 #77 #78 #79 #80

Layout: unified · split

Admin.org +24 −4
@@ -231,6 +231,7 @@ gitbayd admin stats [--json] # counts, database size, per-repo disk
231231ssh git@<host> admin stats [--json] # the same, from an admin session
232232gitbayd admin gc [--repo owner/name] # git gc: repack and prune; per-repo sizes
233233gitbayd admin gc --aggressive # thorough repack; slow, rarely needed
234gitbayd admin gc --lfs # also drop LFS objects no pointer names (older than a day)
234235#+end_src
235236
236237=deploy/cloud-init.yaml= ships a =gitbay-gc.timer= that runs =admin gc=
@@ -242,6 +243,7 @@ import is worthwhile.
242243
243244#+begin_src sh
244245gitbayd admin backup --out /var/backups/gitbay/backup.tar.gz
246gitbayd admin backup --verify /var/backups/gitbay/backup.tar.gz # read it back
245247#+end_src
246248
247249One archive: a consistent SQLite snapshot (taken *before* the
@@ -250,6 +252,11 @@ archive missed), every repository, and the SSH host keys. Excluded:
250252hook socket, regenerated hook scripts, WAL files. Safe to run against a
251253live daemon.
252254
255=--verify= reads an archive back: the snapshot must pass SQLite's
256integrity check, and every repository the snapshot names must be in the
257archive. A database-only archive is checked for integrity and says so.
258Exit is non-zero on damage or a missing repository.
259
253260Restore: extract into an empty directory, point =server.root= at it,
254261start gitbayd. Host keys are preserved, so clients keep their
255262known_hosts entries; hooks regenerate at startup.
@@ -319,6 +326,12 @@ the runner on the server itself. The scoping is what the runner asks for,
319326not an ACL the server holds over it: a runner account is admin by
320327necessity, so the boundary is you choosing how to start it.
321328
329=gitbay dashboard= and =ssh git@<host> admin runners= list every account
330that has polled as a runner: when it last polled, the =-repos= scope it
331asked for, and the build it holds. A build a runner claimed and never
332reported is failed by the scheduler's minute tick, whether or not any
333runner is still alive.
334
322335Instance admin on the runner account only authorizes the claim/report
323336protocol; it grants no repo access. A build that pushes back — a pages
324337deploy, an archive publish, an automated MR branch — needs an explicit
@@ -374,10 +387,17 @@ trusts and refuses to do. Operational checklist:
374387- *Admin sshd (2222)* is throttled by =MaxStartups=/=MaxAuthTries= and
375388 watched by =fail2ban=; gitbayd's own port 22 is throttled by
376389 =limits.ssh_auth_rate= (auth failures per IP per minute).
377- *Monitoring.* =gitbay-monitor.timer= posts disk/service/cert status
378 hourly to the webhook URL in =/etc/gitbay/monitor.url= (create the
379 file to enable; absent = silent). Alerts fire on a stopped service or
380 disk ≥ 85%.
390- *Monitoring.* =gitbay-monitor.timer= writes a reading hourly to
391journald and, when =/etc/gitbay/monitor.url= exists, posts it to that
392webhook: disk, service, the daemon's own =/healthz= answer, certificate
393expiry, and the age of the newest full backup and database snapshot.
394It exits non-zero on an alert so the unit shows in =systemctl
395--failed=: a stopped service, =/healthz= not answering =ok=, disk ≥ 85%,
396a certificate under 21 days, a full backup over 25 hours old, or a
397database snapshot over 2 hours old.
398
399=GET /healthz= is unauthenticated and cache-free: whether the database
400answers and which commit serves, 503 when it does not.
381401- *Database.* =gitbay.db= and its WAL live under =/var/lib/gitbay= (mode
382402 0750, owned by =gitbay=). The nightly archive plus provider snapshots
383403 are the recovery path; for tighter RPO, add continuous replication