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