diff options
Diffstat (limited to 'f3s/forgejo/README.md')
| -rw-r--r-- | f3s/forgejo/README.md | 123 |
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. |
