Audit Forgejo branch-heavy storage growth and define safe retention cleanup #490
Labels
No labels
burndown-2026-06
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/infrastructure#490
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context: follow-up from infrastructure#488. The disk guardrail sweep landed xrdp/journald/rootfs telemetry and documented a read-only Forgejo PVC hotspot drill, but Kai called out that Forgejo is the critical service and that branches are the biggest durable-content offender. This needs its own focused issue because #488 is closed and destructive cleanup was explicitly out of scope.
Goal:
Constraints:
rminside the PVCReferences:
deploy/forgejo.ymldocs/forgejo-deploy-plan-followups.mddocs/ansible-kai-disk-guardrails-role.md🔎 ward agent advisor
ward agent advisor --harness codexran a one-shot standard research pass on this question:Recommendation
Treat this as a single-repo docs/config follow-up, not a multi-repo fan-out. The safest advisory is:
rminside the PVC. On this deployment, raw filesystem deletion is the high-risk path because the whole Forgejo work tree is mounted on onelocal-pathPVC.What is likely growing
Local repo context:
deploy/forgejo.ymlmounts a singlelocal-pathPVC namedforgejo-dataat/var/lib/gitea, requested at 20Gi, while Postgres lives on a separate 5Gi PVC. Actions and LFS are enabled, and there are no explicit storage, retention, package-limit, or quota overrides in the manifest today. See deploy/forgejo.yml lines 39-49 and 174-280./var/lib/gitea/dataand explicitly say to prefer Forgejo UI/API cleanup over truncating the PVC. See docs/forgejo-deploy-plan-followups.md lines 7-13 and docs/ansible-kai-disk-guardrails-role.md lines 50-62.The main storage nuance is that branches are not large by themselves. A branch ref is tiny. Branch-heavy growth becomes durable when many long-lived branches keep unique Git objects reachable, which prevents packfiles from shrinking.
For this deployment, the likely hot paths are:
/var/lib/gitea/git/repositories./var/lib/gitea/dataaccording to Forgejo v15 storage docs:lfs/packages/actions_artifacts/actions_log/repo-archive/attachments/One more important separation: Forgejo’s own docs say Actions cache is stored by the runner itself and never sent to Forgejo. In this repo, the runner also has its own PVCs and an
emptyDirfor Docker state, so runner cache pressure is not the same thing as Forgejo server PVC pressure. See deploy/forgejo-runner.yml and Forgejo Actions admin docs.Safe managed cleanup vs unsafe cleanup
Safe managed cleanup
cron.deleted_branches_cleanupenabled,OLDER_THAN = 24h.cron.git_gc_reposafter branch cleanup.cron.archive_cleanupenabled.OLDER_THAN = 24h.LOG_RETENTION_DAYS = 365,ARTIFACT_RETENTION_DAYS = 90.actions_log/andactions_artifacts/.cron.cleanup_packagesonly removes unreferenced package data older than24hby default. It is not a policy for deleting package versions that are still intentionally present.size:repos:all,size:git:lfs,size:assets:artifacts, andsize:assets:packages:all.Unsafe cleanup
rm -rfinside/var/lib/gitea/git/repositories,/var/lib/gitea/data/lfs,/var/lib/gitea/data/packages,/var/lib/gitea/data/actions_*, or any other Forgejo-managed subtree.Those paths can desynchronize Forgejo’s database, break repository integrity, or remove data that Forgejo still believes exists.
What Forgejo does not give you out of the box
The docs point to a real gap that matters for this issue:
So the branch-retention decision is operational, not automatic. If Kai wants branch-heavy growth controlled, the actual levers are:
Recommended retention defaults
These are the defaults I would recommend documenting first, because they protect Forgejo without surprising normal Git use:
cron.archive_cleanupat 24h.cron.deleted_branches_cleanupat 24h.cron.git_gc_repos, scheduled off-hours.@every 72hcadence or a similar off-hours interval.If Kai wants a single “protect Forgejo first” bias, the best first config changes are:
Those three reduce durable local-path growth without touching live Git history.
Read-only measurement checklist
The existing checklist should be widened beyond
/var/lib/gitea/data, because the most branch-heavy path is probably in/var/lib/gitea/git.1. Top-level Forgejo PVC split
Goal: separate
git/fromdata/.2. Existing documented data-subtree drill
Goal: identify
lfs,packages,actions_artifacts,actions_log,repo-archive,attachmentshotspots.3. Largest repositories on disk
Goal: find which repos actually account for Git growth.
4. Largest packfiles
Goal: confirm packfile-heavy repos rather than loose-file noise.
5. Branch counts on the largest repos
For a suspect repo path:
Goal: distinguish “many refs” from “few refs but very large history”.
6. Postgres size sanity check
Goal: confirm whether DB growth is material or incidental.
7. Largest DB relations
Goal: identify whether Actions/package metadata tables are becoming abnormal.
8. Admin cron status review
In Forgejo admin UI, review
admin/monitor/cron:Open questions to resolve before any live cleanup
git/repositories,lfs,packages,actions_artifacts, or something else?Advisory conclusion
The best answer to post back on the issue is:
data/subtree. The dominant branch-heavy growth is more likely the Git repo store under/var/lib/gitea/git/repositories, while/var/lib/gitea/dataholds other Forgejo-managed assets.Sources
Researched and posted automatically by
ward agent advisor --harness codex(ward#179). This is one-shot research, not a carried change - verify before acting on it.— Codex, via
ward agentWARD-RESERVATION: held 🔒
reservation details
Holder: container
engineer-codex-infrastructure-490on hostkais-macbook-pro-2.local.Reserved by
ward agent --harness codex(reserved 2026-07-10T12:13:03Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (1h TTL).--forceoverrides.Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh. That is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).
run seed context — what this run is carrying (ward#609)
coilyco-flight-deck/infrastructure#490· branchissue-490· harnesscodex· workflowdirect-mainengineer-codex-infrastructure-490· wardv0.580.0· dispatched2026-07-10T12:13:03ZStatic container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.580.0).
— Codex, via
ward agent