infra: track the Forgejo compose file

The only description of how git.levineuwirth.org is deployed lived on the
VPS itself, which meant recovering the deployment required first recovering
the machine — or unpacking a backup tarball to read its own compose file.
It belongs with nginx/ and systemd/.

Recorded in the header rather than lost to shell history: that DOMAIN,
SSH_DOMAIN and ROOT_URL were placeholder text until today; that
FORGEJO__* variables reach app.ini on container recreation and not on
restart; that 3000 is bound to loopback on purpose; and that SSH on 2222,
while genuinely open on the host, is filtered by enough public networks to
be the convenience path rather than the dependable one.

Also removes the caddy container and its leftovers from that box (not
tracked here, but the reason belongs with this change): created at initial
setup in March, never started once — it wanted host ports 80 and 443,
which nginx already held. Its Caddyfile did exactly what nginx now does,
and its data directories were empty. It carried restart=unless-stopped
next to a stale compose backup, so the only thing it could still plausibly
do was win a race for 443 against the server actually serving the site.

NO_REPLY_ADDRESS is set here too, now that checking showed nothing depends
on the old value: the account does not hide its email and no address in the
database sits on a noreply domain, so there was no attribution to orphan.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUGesXiMmACsLBTGG1xuEU
This commit is contained in:
Levi Neuwirth 2026-08-11 13:49:30 +02:00
parent 5711aafa78
commit 0d0794fbf0
No known key found for this signature in database
1 changed files with 65 additions and 0 deletions

View File

@ -0,0 +1,65 @@
# Forgejo deployment for git.levineuwirth.org.
#
# Lives at /root/forgejo-server/docker-compose.yml on the VPS; this copy is
# the tracked source, in the same spirit as nginx/ and systemd/. Until
# August 2026 it existed only on that box, which meant the sole description
# of how the forge was deployed was inside its own backup tarball.
#
# scp forgejo/docker-compose.yml root@<vps>:/root/forgejo-server/
# ssh root@<vps> "cd /root/forgejo-server && docker compose up -d"
#
# Environment variables of the form FORGEJO__section__KEY are applied to
# /data/gitea/conf/app.ini by the entrypoint at startup. They take effect on
# container *recreation*, not on restart — `docker compose up -d` after an
# edit here, not `docker restart forgejo`.
#
# Notes on specific settings:
#
# DOMAIN / SSH_DOMAIN / ROOT_URL — these read git.yourdomain.com until
# 2026-08-11. nginx proxied around the mistake so the site worked, but
# Forgejo generates clone URLs, redirects, and mail links from ROOT_URL,
# so all of those were wrong.
#
# SSH_PORT 2222 — published on 0.0.0.0 and open on the host, but filtered
# by many public networks (it is unreachable from at least one Copenhagen
# library). Clone over HTTPS; treat SSH as the convenience path, not the
# dependable one.
#
# 3000 is bound to 127.0.0.1 deliberately: the web UI is reachable only
# through the host's nginx, never directly.
#
# The database is SQLite at forgejo-data/gitea/gitea.db. Backups are
# systemd/forgejo-backup.{service,timer} driving tools/forgejo-backup.sh.
services:
forgejo:
image: codeberg.org/forgejo/forgejo:1.21.11-0
container_name: forgejo
restart: unless-stopped
environment:
USER_UID: "1000"
USER_GID: "1000"
FORGEJO__server__DOMAIN: git.levineuwirth.org
FORGEJO__server__SSH_DOMAIN: git.levineuwirth.org
FORGEJO__server__ROOT_URL: https://git.levineuwirth.org/
FORGEJO__server__SSH_PORT: "2222"
FORGEJO__database__DB_TYPE: sqlite3
FORGEJO__service__DISABLE_REGISTRATION: "true"
FORGEJO__service__NO_REPLY_ADDRESS: noreply.git.levineuwirth.org
FORGEJO__actions__ENABLED: "false"
volumes:
- ./forgejo-data:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:22"
- "127.0.0.1:3000:3000" # Exposes web UI only to the local Nginx server
networks:
- proxy-net
security_opt:
- no-new-privileges:true
mem_limit: 512m
cpus: 1.0
networks:
proxy-net:
external: true