diff --git a/Caddyfile b/Caddyfile index 1fdc4ec..72c6a37 100644 --- a/Caddyfile +++ b/Caddyfile @@ -9,3 +9,7 @@ www.nazareonline.com.br, nazareonline.com.br { sync.waldson.com.br { reverse_proxy syncthing-syncthing-1:8384 } + +git.waldson.com.br { + reverse_proxy forgejo-forgejo-1:3000 +} diff --git a/README.md b/README.md index fe5519b..a37e13a 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ Caddyfile one site block per app; each reverse_proxies to a container reachable by name on proxy_net syncthing/ the Syncthing stack (own compose file); GUI behind Caddy, sync protocol published on 22000 +forgejo/ the Forgejo stack (own compose file); web UI behind Caddy, + git-over-SSH published on 2222 ``` ## Prerequisites @@ -133,6 +135,92 @@ These steps are done once by the owner at `https://sync.waldson.com.br`: torque-data) with the droplet and accept them on the droplet, pointing each folder path under `/var/syncthing` so the data lands in the bind mount. +## Forgejo stack + +A single-user Forgejo instance (the owner's self-hosted git server) at +`git.waldson.com.br`. It lives in `forgejo/` and deploys to +`/home/waldson/central-proxy/forgejo` on the droplet. + +Only git-over-SSH is published on the host (`2222/tcp`), so the host's admin +sshd keeps port 22. The web UI (`3000`) is **not** published; it is reached only +through Caddy at `git.waldson.com.br`. The central `Caddyfile` carries the +`git.waldson.com.br` block. SQLite is the database, and the whole instance is +configured from environment variables in `compose.yaml` (registration disabled, +Forgejo Actions disabled, correct clone-URL host/port), so the security posture +is reproduced on every recreate rather than depending on installer clicks. + +### Where data lives + +Everything - git repositories, the SQLite database (`/data/gitea/gitea.db`), the +generated `app.ini`, and the container's SSH host keys - lives in the +`forgejo_data` named Docker volume mounted at `/data`. That one volume is the +entire instance, so `docker compose up -d --force-recreate` preserves all users +and repositories. Never `docker volume rm forgejo_data`: it discards every repo +and account. (Off-site backup of this volume is a separate slice: a nightly +`forgejo dump` into a Syncthing-shared folder.) + +### Deploy + +From `forgejo/` on the droplet: + +```sh +docker compose up -d +``` + +The container comes up as `forgejo-forgejo-1` on `proxy_net`, which is the name +Caddy reverse-proxies to. Recreating it preserves users and repositories: + +```sh +docker compose up -d --force-recreate +``` + +### First-run setup (interactive) + +The web installer is locked (`INSTALL_LOCK=true`), so the single admin account +is created from the CLI once, after the container is first up: + +```sh +docker exec -u git forgejo-forgejo-1 \ + forgejo admin user create \ + --admin --username --email \ + --random-password --must-change-password +``` + +Log in at `https://git.waldson.com.br`, change the password, and add your SSH +public key under Settings -> SSH / GPG Keys. Registration is already disabled, so +there is no sign-up path for anyone else. + +### Cloning over SSH (port 2222) + +Forgejo advertises `ssh://git@git.waldson.com.br:2222//.git`. To keep +remotes short (`git@git.waldson.com.br:/.git`) on a personal machine, +add this to `~/.ssh/config`: + +``` +Host git.waldson.com.br + HostName git.waldson.com.br + Port 2222 + User git + IdentityFile ~/.ssh/id_ed25519 +``` + +With that entry, `git clone git@git.waldson.com.br:/.git` works +without spelling out the port. HTTPS clone/pull works through Caddy with no SSH +setup at all: `git clone https://git.waldson.com.br//.git`. + +### Upgrade + +The image is pinned to a Forgejo major version (`codeberg.org/forgejo/forgejo:11`). +Patch and minor updates within that major are safe: + +```sh +docker compose pull && docker compose up -d +``` + +A major bump (editing the tag to the next number) runs one-way database +migrations. Do it one major at a time, back up `forgejo_data` first, and read the +Forgejo release notes before changing the tag. + ## Droplet groundwork Baseline host configuration for the droplet (`wloud`, 174.138.36.232, diff --git a/forgejo/compose.yaml b/forgejo/compose.yaml new file mode 100644 index 0000000..947066d --- /dev/null +++ b/forgejo/compose.yaml @@ -0,0 +1,65 @@ +name: forgejo + +# Single-user Forgejo instance behind the central Caddy proxy at +# git.waldson.com.br. The web UI is reached only through Caddy on proxy_net (the +# HTTP port is never published); git-over-SSH is published on host port 2222 so +# the host's own sshd keeps port 22. All state (repos, the SQLite database, and +# the generated app.ini) lives in the forgejo_data volume. See README.md for the +# deploy, admin-creation, and upgrade runbook. + +services: + forgejo: + # Pinned to a major version: Forgejo major upgrades run one-way database + # migrations, so bump this tag deliberately (see the upgrade runbook) rather + # than tracking latest. + image: codeberg.org/forgejo/forgejo:11 + restart: unless-stopped + environment: + # Own the repos and SQLite file as the droplet's deploy user, matching the + # Syncthing stack, so state is manageable over plain SSH. + USER_UID: "1000" + USER_GID: "1000" + # All configuration is injected here and written into app.ini on startup, + # so the security posture (registration off, Actions off) is reproduced on + # every recreate and does not depend on installer choices. + FORGEJO__database__DB_TYPE: sqlite3 + FORGEJO__database__PATH: /data/gitea/gitea.db + # Public-facing identity. ROOT_URL and SSH_DOMAIN drive the clone URLs the + # UI shows; without them Forgejo would advertise its container hostname. + FORGEJO__server__DOMAIN: git.waldson.com.br + FORGEJO__server__SSH_DOMAIN: git.waldson.com.br + FORGEJO__server__ROOT_URL: https://git.waldson.com.br/ + FORGEJO__server__HTTP_PORT: "3000" + # SSH_PORT is what the UI puts in ssh:// clone URLs (the published host + # port); SSH_LISTEN_PORT is the container-internal sshd that host 2222 maps + # to. Keeping them distinct lets the host sshd keep port 22. + FORGEJO__server__SSH_PORT: "2222" + FORGEJO__server__SSH_LISTEN_PORT: "22" + # No sign-up path for strangers; the single admin is created out of band + # via the CLI (see the runbook). + FORGEJO__service__DISABLE_REGISTRATION: "true" + # Skip the web installer entirely: the instance is fully configured above, + # and locking it stops anyone from re-running install to change these. + FORGEJO__security__INSTALL_LOCK: "true" + # No CI runners on the 2 GB droplet. + FORGEJO__actions__ENABLED: "false" + volumes: + # Repos, the SQLite database, generated config, and SSH host keys all live + # under /data, so this one volume is the entire instance. It is never + # removed casually (see the runbook). + - forgejo_data:/data + ports: + # git-over-SSH only. Host 2222 -> container sshd on 22, so the host's admin + # sshd on 22 is untouched. HTTP (3000) is deliberately unpublished; Caddy + # reaches it by container name on proxy_net. + - "2222:22" + mem_limit: 768m + networks: + - proxy_net + +networks: + proxy_net: + external: true + +volumes: + forgejo_data: