Upload files to "/"

This commit is contained in:
rufusking 2026-07-26 22:14:10 -04:00
parent fc5f92c54a
commit 48d1219bd3

251
server_forgejo.md Normal file
View file

@ -0,0 +1,251 @@
# Forgejo — Self-Hosted Git Server
Device Type: **Docker Container (hosted on NAS16)**
Hostname: **forgejo**
IP Address: **192.168.150.40** (shares NAS16's host IP)
VLAN: **50 — Lab / Servers**
Last Updated: 2026-07-26
---
## 🧩 Role & Purpose
Forgejo is the **self-hosted Git server and file version-control system** for the KingDezigns network. It provides a web UI for browsing, editing, and tracking revision history of scripts, configs, and project files — replacing ad-hoc file copies and manual backups with real version control.
Forgejo was chosen over Gitea specifically for its **non-profit, community-run governance model** (Codeberg e.V.) — consistent with the KingDezigns philosophy of avoiding dependency on third-party business decisions (same reasoning behind self-hosted DNS, self-hosted reverse proxy, and self-hosted stock price API). Functionally, Forgejo and Gitea are near-identical since Forgejo is a fork of Gitea; the choice was governance, not features.
This server hosts version-controlled copies of the scripts and project files that live under the network's `07 - Projects` share, organized per host.
---
## 🌐 Network Placement
- VLAN: **50 — Lab / Servers**
- Host: **NAS16** (192.168.150.40)
- Access Type: LAN / Cable (web UI also reachable externally via NPM)
Chosen over NAS08 or PLEX32 because NAS16 has **the most headroom of any Pi in the fleet** (16GB RAM, consistently underutilized) — the same reasoning already used to place the CrowdSec notifier scripts on NAS16 instead of HAS. NAS08 is the busiest box (DNS, Nextcloud, ONLYOFFICE, Collabora, Vaultwarden, STOCKPROXY) and PLEX32's CPU headroom exists specifically for Quick Sync transcoding — neither is a good fit for an always-on secondary service.
This placement is subject to VLAN 50's normal containment rules — see [firewall_policies.md](firewall_policies.md). No firewall changes were required to stand this up; existing VLAN 1/20 → VLAN 50 inbound rules and NAS16's local traffic already covered everything needed.
---
## 📦 Primary Functions
### **Core Service**
- **Forgejo** (Docker — `codeberg.org/forgejo/forgejo:10`)
- SQLite database (appropriate at this scale — no separate DB container)
- Web UI for repository browsing, in-browser file editing, and commit history
- SSH-based git access (clone/push/pull) on a dedicated port
- Git-over-HTTPS also available via the public web URL
### **Public Access**
- **Domain:** `https://forgejo.kingdezigns.com/`
- **Proxy:** NPM on HAS (192.168.150.30) → `192.168.150.40:3000`
- **SSL:** Let's Encrypt via NPM, Force SSL enabled — same pattern as all other KingDezigns public services
- **SSH clone/push:** LAN-only for now — `ssh://git@192.168.150.40:2222/...`. Not exposed externally (no UCG Max port-forward configured). External SSH access is a possible future addition; HTTPS clone via the public domain works from anywhere in the meantime.
### **Organizations & Repository Convention**
Each host in the network gets its own Forgejo **Organization**, matching the `07 - Projects` folder structure on NAS16's share. Each organization currently holds a single repository named `<hostname>-scripts`.
| Organization | Repository | Source Folder (on NAS16) |
|---|---|---|
| `NAS08` | `nas08-scripts` | `/export/kingdezignsnas-16/Public/07 - Projects/NAS08` |
| `NAS16` | `nas16-scripts` | `/export/kingdezignsnas-16/Public/07 - Projects/NAS16` |
| `PLEX32` | `plex32-scripts` | `/export/kingdezignsnas-16/Public/07 - Projects/PLEX32` |
This convention (`<HOSTNAME>` org → `<hostname>-scripts` repo) is expected to extend to future hosts (e.g. HAS) as they're added to version control.
> Note: All three Projects folders live on the same NFS share on NAS16 — there is no need to install `git` or SSH keys on NAS08 or PLEX32 themselves. All git operations for all three repos are run **from NAS16**, simply `cd`-ing into the relevant subfolder.
---
## 🐳 Docker Configuration
### **Compose File Location**
Managed via OMV → Services → Compose, project name `forgejo`.
### **Compose Contents**
```yaml
services:
forgejo:
image: codeberg.org/forgejo/forgejo:10
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1001
- FORGEJO__database__DB_TYPE=sqlite3
- FORGEJO__server__ROOT_URL=https://forgejo.kingdezigns.com/
- FORGEJO__server__DOMAIN=forgejo.kingdezigns.com
- FORGEJO__server__SSH_PORT=2222
- FORGEJO__server__SSH_LISTEN_PORT=22
volumes:
- /opt/forgejo/data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:22"
restart: unless-stopped
```
> **UID/GID 1000/1001:** Matches the existing `ncshare` group convention used across NAS08, NAS16, and PLEX32 for permission consistency.
### **Key Docker Commands**
```bash
# Start
cd /path/to/omv/compose/project/forgejo && sudo docker compose up -d
# Stop
cd /path/to/omv/compose/project/forgejo && sudo docker compose down
# Update Forgejo (recreates container to pick up new image + env vars)
cd /path/to/omv/compose/project/forgejo && sudo docker compose pull && sudo docker compose up -d
# View logs
sudo docker logs forgejo --tail 50
# Check container status
sudo docker ps
```
> **Note:** `docker restart forgejo` restarts the existing container with its *already-loaded* environment — it does **not** re-read Compose file changes. Any edit to environment variables in the Compose file requires `docker compose up -d`, not `docker restart`, to actually take effect. This was the root cause of an initial `ROOT_URL` mismatch — see Troubleshooting History below.
### **Docker Group Membership**
`rufusking` was not initially in the `docker` group on NAS16, requiring `sudo` for all `docker`/`docker compose` commands. Add to group for passwordless docker access going forward:
```bash
sudo usermod -aG docker rufusking
```
(requires logout/login or `newgrp docker` to take effect)
---
## 🔐 SSH Access
- **SSH clone command:** `ssh://git@192.168.150.40:2222/<ORG>/<repo>.git`
- **Port:** 2222 (mapped to container's internal port 22) — chosen to avoid colliding with each host's own SSH daemon on port 22
- **Auth:** SSH public key only, added per-user under **Settings → SSH/GPG Keys** in the Forgejo web UI
- **Scope:** LAN-only — no UCG Max port-forward configured for 2222
### **Adding a new SSH key (per host/user)**
```bash
ssh-keygen -t ed25519 -C "user@hostname-forgejo"
cat ~/.ssh/id_ed25519.pub
```
Paste the output into Forgejo: **Settings → SSH/GPG Keys → Add Key**.
Test:
```bash
ssh -T -p 2222 git@192.168.150.40
```
Expected response (this is success, not an error):
```
Hi there, <username>! You've successfully authenticated with the key named <key-name>, but Forgejo does not provide shell access.
```
> Note: Because the Compose file grants `docker` group access only after re-login, and because the Forgejo container's internal `authorized_keys` file is separate from the host's own SSH config, a key must be explicitly added via the Forgejo web UI — it is **not** sufficient to have a key that works for host-level SSH into NAS16 itself.
---
## 📝 Day-to-Day Workflow — Editing Files
Files under `07 - Projects/<HOST>` can be edited two ways, both fully supported:
### **1. Web UI (Forgejo)**
Browse to the repo, open a file, click the edit (pencil) icon, make changes, and commit directly from the browser. Best for quick one-off edits or browsing history/diffs.
### **2. Directly on the NFS share (local edit)**
Since each Projects subfolder is a real git working directory, files can be edited by any method (Nano, a text editor, another script) directly on the share. Changes are **not** automatically tracked — git does not watch the folder — so they must be explicitly staged, committed, and pushed:
```bash
cd "/export/kingdezignsnas-16/Public/07 - Projects/<HOST>"
git add .
git commit -m "describe what changed"
git push
```
- `git status` beforehand is optional — useful only to preview what changed.
- Uncommitted local changes are not lost if you forget to push; the commit still exists locally and can be pushed later with a plain `git push`.
- Pulling before editing locally (`git pull`) is good practice if the same file might also be edited via the web UI, to avoid merge conflicts.
---
## 🔒 Required Firewall Behavior
### **Inbound to Forgejo (via NAS16, 192.168.150.40)**
- Allowed from VLAN 1 and VLAN 20 (global VLAN 50 inbound rules)
- Allowed from local VLAN 50 traffic
- External web traffic (`https://forgejo.kingdezigns.com/`) arrives via NPM on HAS (192.168.150.30), same as all other public KingDezigns services
- Port 2222 (SSH) is **not** forwarded externally — LAN-only
### **Outbound from Forgejo**
- Subject to VLAN 50's global final drop, same as all NAS16 services — no outbound access to other VLANs
- No outbound dependencies beyond local DNS (Pi-hole)
No new firewall rules were required for this deployment — it operates entirely within NAS16's existing inbound/outbound rule set.
---
## 💾 Backup
Forgejo's data (SQLite database, repositories, config, SSH host keys) lives entirely under `/opt/forgejo/data` on the NAS16 host filesystem (bind-mounted, not a Docker volume) — making it straightforward to fold into NAS16's existing backup routine.
- **Data path:** `/opt/forgejo/data`
- **Backup method:** Folded into the existing `/usr/scripts/omv/nas16-backup.sh` OMV Scheduled Job (every 3 days at 2:00 AM) — no separate/dedicated backup job created
- **Restore consideration:** Restoring `/opt/forgejo/data` and recreating the container (`docker compose up -d`) is expected to fully restore Forgejo, since all state (repos, DB, config, SSH host keys) lives under that single path — not yet tested end-to-end as of this writing
> Note: Because `07 - Projects` files are *also* independently backed up as part of NAS16's normal share backups, project files are effectively protected twice — once as plain files on the share, and once as full git history inside Forgejo's data volume.
---
## 🛠️ Troubleshooting History (2026-07-26)
### **SSH "Permission denied (publickey)" on initial setup**
**Symptom:** `ssh -T -p 2222 git@192.168.150.40` returned `Permission denied (publickey)` even after generating an SSH keypair on NAS16.
**Root cause:** The generated public key was never actually added to the user's account in the Forgejo web UI (**Settings → SSH/GPG Keys** was empty) — the keypair existing locally does nothing until the public half is registered server-side.
**Fix:** Pasted the full `id_ed25519.pub` contents into Forgejo's **Add Key** form. Verified success via the "successfully authenticated... does not provide shell access" response (this message is expected and indicates success, not failure).
### **"Push to create is not enabled for organizations"**
**Symptom:** `git push` failed with this error even after a successful local commit.
**Root cause:** The target repository (e.g. `PLEX32/plex32-scripts`) did not yet exist on the server — Forgejo does not auto-create repositories on push by default (a deliberate security default, left enabled).
**Fix:** Create the repository via the web UI first (**Organization → New Repository**, left uninitialized — no README/gitignore) before pushing.
### **ROOT_URL mismatch warning after adding NPM/domain**
**Symptom:** After proxying Forgejo through NPM at `https://forgejo.kingdezigns.com/`, login displayed: *"Your ROOT_URL in app.ini is 'http://192.168.150.40:3000/', it's unlikely matching the site you are visiting."*
**Root cause:** `ROOT_URL` (and `DOMAIN`) were still set to the internal IP:port from initial setup. A mismatched `ROOT_URL` produces broken links in generated clone commands, notification emails, webhook payloads, and OAuth2 callbacks — not just cosmetic.
**Dead end encountered:** Editing `/data/gitea/conf/app.ini` directly (via `vi` inside the container, or `sed`) appeared to succeed and verified correctly immediately after the edit — but reverted to the old value on every `docker restart forgejo`. This is because the Compose file's `FORGEJO__server__ROOT_URL` environment variable overrides `app.ini` on every container start; a `restart` re-applies the container's existing (stale) environment rather than re-reading Compose.
**Fix:** Updated `ROOT_URL` (and added an explicit `DOMAIN`) directly in the Compose file's `environment:` block, then applied with `docker compose up -d` (which recreates the container with the new environment) rather than `docker restart`. Confirmed persistence across a subsequent restart.
**Lesson for future config changes:** Any Forgejo setting exposed as a `FORGEJO__*` environment variable in the Compose file will always win over a manually-edited `app.ini` value on every container start/recreate. Edit the Compose file, not the file inside the container, for any setting that has a corresponding env var.
### **`git: command not found` on NAS16 host**
**Symptom:** Running `git init`/`git add`/etc. from the NAS16 shell failed — git was not installed on the host itself (only inside the Forgejo container, which is unrelated).
**Fix:** `sudo apt-get update && sudo apt-get install -y git`
### **`permission denied while trying to connect to the docker API`**
**Symptom:** Plain `docker exec ...` commands failed for `rufusking` on NAS16.
**Root cause:** `rufusking` was not a member of the `docker` group.
**Fix (immediate):** Prefix commands with `sudo`.
**Fix (permanent, recommended):** `sudo usermod -aG docker rufusking`, then log out/in.
---
## 🧠 Summary for AI Systems
- Forgejo = **self-hosted Git server + web UI for file version control**, running as a Docker container on **NAS16** (192.168.150.40), VLAN 50.
- Chosen over Gitea specifically for non-profit/community governance (Codeberg e.V.) — functionally near-identical to Gitea since it's a fork.
- Placed on NAS16 rather than NAS08 or PLEX32 because NAS16 has the most spare RAM/CPU headroom of the three (same reasoning as the existing CrowdSec notifier placement).
- Image: `codeberg.org/forgejo/forgejo:10`, SQLite database, Compose-managed via OMV.
- Public web UI: `https://forgejo.kingdezigns.com/`, proxied via NPM on HAS, Force SSL + Let's Encrypt.
- SSH git access: `ssh://git@192.168.150.40:2222/...`**LAN-only**, no external port-forward configured (may be added later).
- Registration disabled (`DISABLE_REGISTRATION = true`) — accounts are admin-created only.
- **Organization convention:** one org per host (`NAS08`, `NAS16`, `PLEX32`), one repo per org (`<hostname>-scripts`), matching the `07 - Projects/<HOST>` folder structure on NAS16's share. Expected to extend to future hosts (e.g. HAS).
- **All git operations for all three hosts are run from NAS16** — no git installation or SSH keys needed on NAS08 or PLEX32 themselves, since their Projects folders are on the same NFS share.
- Files can be edited either via the Forgejo web UI (commits directly) or locally on the NFS share (requires manual `git add` / `git commit` / `git push` — changes are **not** auto-tracked).
- Backup: `/opt/forgejo/data` (bind-mounted, contains DB + repos + config + SSH host keys) folded into the existing `nas16-backup.sh` OMV Scheduled Job (every 3 days, 2:00 AM) — no separate backup job.
- **Critical operational lesson:** any `FORGEJO__*` environment variable set in the Compose file overrides `app.ini` on every container start — config changes to settings with an env-var equivalent must be made in Compose + applied via `docker compose up -d`, not by hand-editing `app.ini` or using `docker restart`.
- SSH keys must be registered per-user in the Forgejo web UI (**Settings → SSH/GPG Keys**) — a working host-level SSH key does not automatically grant Forgejo git access.
- Repos must be created via the web UI before first push — "push to create" is disabled for organizations by default (left as-is, not overridden).
- `rufusking` initially lacked `docker` group membership on NAS16 — recommended fix is `usermod -aG docker rufusking` rather than routine `sudo` use.
- Known minor cleanup items from initial imports (not yet addressed): duplicate files in `NAS08/nas08-scripts` (e.g. `nextcloud_update_check (1).sh`, a redundant copy in both `nextcloud/` and `scripts/`, a stray `.html~` backup file) and a possible duplicate `plex32_backup2.sh` in `PLEX32/plex32-scripts` — safe to clean up in a follow-up commit since git history preserves them regardless.
- Restore procedure for `/opt/forgejo/data` has not yet been tested end-to-end.
---
# ✔️ End of File