summaryrefslogtreecommitdiff
path: root/f3s/forgejo/README.md
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-26 09:57:28 +0300
committerPaul Buetow <paul@buetow.org>2026-07-26 09:57:28 +0300
commita3f216fc2cce2299cf66e174fb927cc05dde97dd (patch)
treec8b89ccbd7c81c3a11a6a6e7872efc77b0b7dfb9 /f3s/forgejo/README.md
parentaaa786fcea8de25be1bd2eff8bc35afd1bc7482a (diff)
forgejo: add a standalone Forgejo install at code.f3s.buetow.org
Deliberately independent of the cgit git-server: separate namespace (services), separate NFS volumes, separate SSH NodePort (30222 vs 30022), and no shared storage. cgit keeps serving the existing 80 bare repos at c-git.f3s.buetow.org and is not touched. Forgejo starts empty; repos get migrated by hand later. ArgoCD deliberately keeps reading conf.git from the existing git-server, so Forgejo has no consumers and cannot take cluster deploys down with it. SQLite rather than a PostgreSQL pod: single writer (replicas 1 + Recreate) and NFSv4.2 does real byte-range locking, so the usual SQLite-on-NFS failure mode does not apply. Uses the -rootless image so the pod runs wholly as UID 1000 with all capabilities dropped, and both volumes carry the .nfs-sentinel guard. The installer is locked and registration disabled because the instance is reachable from the internet; the admin account is created via the CLI. code.f3s.buetow.org added to @f3s_hosts, which drives the DNS zone, the relayd route, the ACME cert and the gogios checks. Not yet activated: the ArgoCD Application still needs applying, the NFS directories creating, and the frontends deploying. See f3s/forgejo/README.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'f3s/forgejo/README.md')
-rw-r--r--f3s/forgejo/README.md123
1 files changed, 123 insertions, 0 deletions
diff --git a/f3s/forgejo/README.md b/f3s/forgejo/README.md
new file mode 100644
index 0000000..ecc35a6
--- /dev/null
+++ b/f3s/forgejo/README.md
@@ -0,0 +1,123 @@
+# Forgejo
+
+Self-hosted git forge at `https://code.f3s.buetow.org`, running in the `services`
+namespace of the f3s k3s cluster.
+
+## Relationship to the cgit git-server
+
+**These two installs are deliberately independent.** Nothing here touches
+`f3s/git-server/`:
+
+| | cgit / git-server | Forgejo |
+|---|---|---|
+| Web UI | `c-git.f3s.buetow.org` | `code.f3s.buetow.org` |
+| Namespace | `cicd` | `services` |
+| Repo storage | `/data/nfs/k3svolumes/git-server/repos` (80 bare repos) | `/data/nfs/k3svolumes/forgejo/data` (starts empty) |
+| SSH NodePort | 30022 | 30222 |
+
+ArgoCD keeps reading `conf.git` from the existing git-server
+(`http://git-server.cicd.svc.cluster.local/conf.git`). Forgejo has no consumers,
+so if it breaks, cluster deploys are unaffected. Repositories are migrated by
+hand, one at a time, whenever you feel like it — there is no bulk import.
+
+## Architecture
+
+```
+Internet -> relayd (OpenBSD GW, TLS) -> WireGuard -> Traefik -> forgejo svc:80 -> pod:3000
+git+ssh -> NodePort 30222 -----------------------------------> pod:2222
+ |
+ /var/lib/gitea (repos, SQLite) NFS -> ZFS
+ /etc/gitea (app.ini, secrets)
+```
+
+- Image `codeberg.org/forgejo/forgejo:16.0.1-rootless` — the rootless variant, so
+ the whole pod runs as UID/GID 1000 with all capabilities dropped.
+- SQLite, not PostgreSQL. Single writer (`replicas: 1` + `Recreate`), and NFSv4.2
+ does real byte-range locking, so the classic SQLite-on-NFS corruption mode does
+ not apply. Revisit if this ever needs to scale out.
+- Both volumes carry the standard `.nfs-sentinel` guard so the pod refuses to
+ start against the local-XFS shadow if a node has NFS unmounted.
+
+## Initial setup
+
+### 1. Create the storage directories
+
+On the current CARP storage master (check with `ifconfig | grep MASTER` on f0/f1):
+
+```sh
+doas mkdir -p /data/nfs/k3svolumes/forgejo/data /data/nfs/k3svolumes/forgejo/config
+doas touch /data/nfs/k3svolumes/forgejo/data/.nfs-sentinel \
+ /data/nfs/k3svolumes/forgejo/config/.nfs-sentinel
+doas chown -R 1000:1000 /data/nfs/k3svolumes/forgejo
+doas chmod -R 0750 /data/nfs/k3svolumes/forgejo
+```
+
+The PVs use `type: Directory`, so the pod will not schedule until these exist.
+
+### 2. Publish the hostname
+
+`code.f3s.buetow.org` must be added to `@f3s_hosts` in `frontends/Rexfile`. That
+one array drives the DNS zone, the relayd routing rule, the ACME certificate and
+the gogios monitoring checks.
+
+Deploy order matters — relayd loads `tls keypair code.f3s.buetow.org` at startup,
+so the certificate has to exist first:
+
+```sh
+cd frontends
+rex -H blowfish.buetow.org:2 nsd httpd acme acme_invoke relayd
+rex -H fishfinger.buetow.org:2 nsd httpd acme acme_invoke relayd
+```
+
+`acme.sh` copies the `foo.zone` cert as a placeholder for any host that has none
+yet, so relayd will still start on the first pass; the real certificate arrives
+on the same run. Deploying one gateway at a time avoids restarting both public
+frontends simultaneously.
+
+### 3. Deploy
+
+```sh
+kubectl apply -f ../argocd-apps/services/forgejo.yaml
+```
+
+Or just push — ArgoCD picks it up automatically.
+
+### 4. Create the admin user
+
+The web installer is locked (`INSTALL_LOCK=true`) and registration is disabled,
+because this instance is reachable from the public internet. Create the first
+account from the CLI:
+
+```sh
+just create-admin
+```
+
+## Repository URLs
+
+```sh
+# HTTPS
+git clone https://code.f3s.buetow.org/<user>/<repo>.git
+
+# SSH (NodePort; LAN only unless you forward it)
+git clone ssh://git@r0.lan.buetow.org:30222/<user>/<repo>.git
+```
+
+## Operations
+
+```sh
+just status # pods, services, ingress, PVCs, ArgoCD sync
+just logs # follow logs
+just restart # rollout restart
+just shell # shell inside the pod
+just port-forward # reach the UI on localhost:3000
+```
+
+## Backup
+
+Covered by the ZFS snapshots and zrepl replication of `/data/nfs`. The SQLite
+database and `app.ini` both live on that volume. To restore: roll back the ZFS
+snapshot and restart the deployment.
+
+Note that `/etc/gitea/app.ini` holds `SECRET_KEY` and `INTERNAL_TOKEN`, generated
+on first start. Restoring the data volume without the matching config volume
+invalidates sessions and stored credentials.