From 635ad2df35c631161e582a68963bbba56bb3011a Mon Sep 17 00:00:00 2001 From: bot-backend Date: Wed, 16 Sep 2026 22:30:27 +0300 Subject: [PATCH] chore(forgejo): track compose file with retention/cleanup settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit app.ini on prod has no [cron.archive_cleanup] section and no retention keys under [actions] — everything ran on Forgejo defaults (archive cache swept once/24h, no cap on Actions log/artifact age). An external crawler hitting per-commit archive URLs grew repo-archive cache to ~48GB/145GB before the daily sweep caught up; Caddy now blocks that path (#3534), but this is the second line of defense if that rule is ever lifted. Forgejo isn't part of the automated deploy pipeline and its compose file only existed on the host (not a git checkout), so there was nowhere for this config to survive a redeploy or even be reviewed. Adds a tracked copy at ops/forgejo/docker-compose.yml, alongside the existing ops/backup.sh and ops/restore.sh host scripts, with: - [cron.archive_cleanup]: ENABLED/RUN_AT_START=true, SCHEDULE=@every 1h, OLDER_THAN=1h — hourly sweep instead of daily, 1h grace window. - [actions] LOG_RETENTION_DAYS=30, ARTIFACT_RETENTION_DAYS=14 — checked against .forgejo/workflows and .github/workflows first: no workflow uploads/downloads artifacts today, so nothing to break. Key names verified against the running image (Forgejo 10.0.3) by extracting Go struct ini-tags from the binary and dry-running environment-to-ini in a container scratch dir — not from memory, since a wrong key is silently dropped. Not applied to prod. Needs manual scp + `up -d --force-recreate forgejo` per the file's header comment — see PR description. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG --- ops/forgejo/docker-compose.yml | 81 ++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 ops/forgejo/docker-compose.yml diff --git a/ops/forgejo/docker-compose.yml b/ops/forgejo/docker-compose.yml new file mode 100644 index 00000000..d34ec78e --- /dev/null +++ b/ops/forgejo/docker-compose.yml @@ -0,0 +1,81 @@ +# Source-of-truth copy of the Forgejo compose file. +# +# Forgejo is NOT part of the automated deploy pipeline (deploy.yml only +# manages /opt/gendesign via `git reset --hard origin/main` on the main and +# obsidian stacks). Forgejo lives separately at /home/gendesign/forgejo on +# the VM and is a plain directory there — NOT a git checkout — so changes +# here do not auto-apply. Sync manually: +# +# scp ops/forgejo/docker-compose.yml gendesign:/home/gendesign/forgejo/docker-compose.yml +# ssh gendesign "cd /home/gendesign/forgejo && docker compose up -d --force-recreate forgejo" +# +# `up -d --force-recreate` (not `restart`) is required: Forgejo generates +# app.ini from the FORGEJO__* env vars via /usr/local/bin/environment-to-ini +# at container start, and `restart` does not re-read `environment:` from a +# changed compose file (see docker-compose pitfall #1 in devops CLAUDE.md). +# +# Config keys verified 2026-09-16 against the running image +# (codeberg.org/forgejo/forgejo:10, Forgejo 10.0.3+gitea-1.22.0) by +# extracting Go struct tags from the binary (`strings` on +# /app/gitea/gitea) and by a dry-run of environment-to-ini in a scratch +# dir inside the container (no prod files touched). Do not re-derive these +# from memory — a wrong key is silently ignored (empty section) and +# creates a false sense of safety. +# +# Dotted section names ([cron.archive_cleanup]) must be encoded as +# `_0x2E_` in the env var per the container's own +# `environment-to-ini --help` (confirmed empirically, see PR description). +services: + forgejo: + image: codeberg.org/forgejo/forgejo:10 + container_name: forgejo + restart: unless-stopped + environment: + USER_UID: 1000 + USER_GID: 1000 + FORGEJO__database__DB_TYPE: postgres + FORGEJO__database__HOST: infra-postgres:5432 + FORGEJO__database__NAME: forgejo + FORGEJO__database__USER: forgejo + FORGEJO__database__PASSWD: ${FORGEJO_DB_PASS} + FORGEJO__server__DOMAIN: git.gendsgn.ru + FORGEJO__server__ROOT_URL: https://git.gendsgn.ru/ + FORGEJO__server__SSH_PORT: 2222 + FORGEJO__server__SSH_LISTEN_PORT: 22 + FORGEJO__server__START_SSH_SERVER: "false" + FORGEJO__service__DISABLE_REGISTRATION: "true" + FORGEJO__service__REQUIRE_SIGNIN_VIEW: "false" + FORGEJO__actions__ENABLED: "true" + FORGEJO__actions__DEFAULT_ACTIONS_URL: "github" + # Actions Log/artifact retention — was unset (Forgejo defaults), which + # let CI run logs/artifacts accumulate indefinitely. Artifact + # retention checked against .forgejo/workflows + .github/workflows on + # 2026-09-16: no workflow uploads/downloads artifacts today, so 14d + # cannot break a cross-job dependency. Revisit this comment if a + # workflow starts using actions/upload-artifact. + FORGEJO__actions__LOG_RETENTION_DAYS: "30" + FORGEJO__actions__ARTIFACT_RETENTION_DAYS: "14" + # Repo-archive cache cleanup — was entirely absent (no + # [cron.archive_cleanup] section), so it ran on Forgejo's own default + # schedule (once every 24h, deleting archives older than 24h). That + # let an external crawler hitting ///archive/ + # balloon the cache to ~48GB/145GB disk before the daily sweep caught + # up (see PR #3534, which closed the path in Caddy as the primary + # fix). This is the second line of defense if that Caddy rule is ever + # removed: run hourly, evict anything older than 1h. + FORGEJO__CRON_0x2E_ARCHIVE_CLEANUP__ENABLED: "true" + FORGEJO__CRON_0x2E_ARCHIVE_CLEANUP__RUN_AT_START: "true" + FORGEJO__CRON_0x2E_ARCHIVE_CLEANUP__SCHEDULE: "@every 1h" + FORGEJO__CRON_0x2E_ARCHIVE_CLEANUP__OLDER_THAN: "1h" + FORGEJO__security__INSTALL_LOCK: "true" + volumes: + - ./data/forgejo:/data + ports: + - "2222:22" + networks: + - gendesign_default + +networks: + gendesign_default: + external: true + name: gendesign_default -- 2.45.3