diff --git a/README.md b/README.md index c90fa74..ee9e522 100644 --- a/README.md +++ b/README.md @@ -165,12 +165,13 @@ one-off `450 4.7.25 Client host rejected` shows up in `mail.log`. | `web.jayfield.org` | → redirect to :443 | Reverse-proxies to the **Docker `web` (nginx) container** on `127.0.0.1:8081` | New — see below | | `cloud.jayfield.org` | → redirect to :443 | Reverse-proxies to the **Docker `nextcloud` container** on `127.0.0.1:8082`, sets `X-Forwarded-Proto: https` | Nextcloud — see below | | `portainer.jayfield.org` | → redirect to :443 | Reverse-proxies to the **Docker `portainer` container** on `127.0.0.1:9443` over HTTPS (`SSLProxyEngine`/`SSLProxyVerify none` for the loopback hop to Portainer's self-signed cert) | Added 2026-07-20 — see "Portainer" below | +| `git.jayfield.org` | → redirect to :443 | Reverse-proxies to the **Docker `gitea` container** on `127.0.0.1:8083`, sets `X-Forwarded-Proto: https` | Added 2026-07-26 — migrated from `vlda-01`, see "Gitea" below | | default (`_default_:443`, `000-default` on :80) | Apache's stock placeholder page | — | | -All Let's Encrypt certs (8 total, one per hostname/group) auto-renew via +All Let's Encrypt certs (9 total, one per hostname/group) auto-renew via `certbot.timer`; verified with `certbot renew --dry-run`. -All 7 domain `:443` blocks send `Strict-Transport-Security: max-age=63072000; +All 8 domain `:443` blocks send `Strict-Transport-Security: max-age=63072000; includeSubDomains` (`mod_headers`). Deliberately skipped on the `default-ssl.conf` catch-all — it's the self-signed fallback for unmatched SNI/Host headers, not a real trusted hostname a browser could pin. @@ -184,6 +185,7 @@ SNI/Host headers, not a real trusted hostname a browser could pin. | `nextcloud` | `nextcloud:apache` | `127.0.0.1:8082` (localhost-only) | Nextcloud app (PHP+Apache bundled in the image); backing service for `cloud.jayfield.org` | | `nextcloud-db` | `mariadb:lts` | internal only (`nextcloud_net`) | Dedicated DB for Nextcloud — kept separate from the host's own MySQL (which only holds `vmail`) | | `nextcloud-redis` | `redis:alpine` | internal only (`nextcloud_net`) | File locking + distributed cache + PHP session storage for Nextcloud. Dedicated container rather than reusing the host's native `redis-server`, since that instance is bound to `127.0.0.1`/`::1` only with no auth — reusing it would have meant loosening a shared service's network exposure just to save one small container | +| `gitea` | `gitea/gitea:1.27.0` | `127.0.0.1:8083` (localhost-only) | Git hosting, migrated from `vlda-01` 2026-07-26 — see "Gitea" below | Data persists in the `portainer_data` named volume, independent of the container itself — updating Portainer means recreating the container @@ -272,6 +274,62 @@ Internet → Apache :80/:443 (cloud.jayfield.org vhost) (512M `memory_limit`/`upload_max_filesize`/`post_max_size`, unlimited `max_execution_time`) — no tuning needed for this pass. +### Gitea (`git.jayfield.org`) + +Migrated 2026-07-26 from `vlda-01` (home intranet server) per +`SYNC-PLAN.md`'s build order — first item on that plan, "no open +questions." Full migration, not a sync: `vlda-01`'s Gitea container was +stopped, its entire `/data` volume (SQLite DB, all repos, LFS objects, +host SSH keys) copied straight across via a piped `ssh ... tar | ssh ... +tar` (no intermediate disk, ~4GB), and brought up on alpha as a permanent +container — same `web`/`cloud`/`portainer` pattern (publish to +`127.0.0.1:`, Apache vhost, `certbot --apache`). + +``` +Internet → Apache :80/:443 (git.jayfield.org vhost) + → Let's Encrypt TLS termination, X-Forwarded-Proto: https + → ProxyPass http://127.0.0.1:8083/ + → container "gitea" (gitea/gitea:1.27.0) + → SQLite DB + repos, bind-mounted at /srv/gitea/data +``` + +- **Version pinned, not `:latest`**: `gitea/gitea:1.27.0`, matching what + was actually running on `vlda-01` — a version-compatible move first, + upgrading is a separate later decision. +- **Data**: bind-mounted at `/srv/gitea/data` on the host (matching the + `/srv/nextcloud/data` convention — directly inspectable/backupable), + not an opaque named volume. +- **Ownership**: the source data was owned by uid/gid `1000` on + `vlda-01`, but `1000` is already `vmail` on alpha (Dovecot's mailbox + user) — remapped everything to a dedicated `1010:1010` (`chown -R`, + container run with `-e USER_UID=1010 -e USER_GID=1010`) to avoid any + collision with or confusion around the real `vmail` account. +- **SQLite, not the host's MariaDB**: `vlda-01`'s Gitea was already + self-contained SQLite (`DB_TYPE = sqlite3`), so no DB export/import or + extra container was needed — the DB file just came along inside `/data`. +- **`app.ini` updated for the new home**: `DOMAIN`/`SSH_DOMAIN`/`ROOT_URL` + repointed from the old LAN IP (`192.168.22.90`) to `git.jayfield.org`; + `DISABLE_SSH` set to `true` — the existing repo remotes already used + HTTP(S), not `git@.../ssh://`, so git-over-SSH was dropped rather than + opening yet another public port to preserve a mode nothing was actually + using. HTTPS clone/push covers the same ground through the same Apache + TLS termination every other service uses. +- **Reverse-proxy scheme awareness**: without `X-Forwarded-Proto: https` + (added to the vhost, same as `cloud.jayfield.org`), Gitea's API + correctly used `ROOT_URL` for some fields but generated `http://` (not + `https://`) `clone_url`/`html_url` for repos — since the Apache→container + hop itself is plain HTTP and Gitea otherwise has no way to know the + original request arrived over TLS. Fixed and verified via the API. +- **Verified end-to-end**: all previously-existing repos present via the + API (including this `docs-alpha.jayfield.org` repo), admin user + (`jayfield`) intact; a real `git clone` over HTTPS reproduced identical + commit history to the working copy; this repo's own `origin` remote + repointed to `https://git.jayfield.org/...` and a real `git push` + succeeded against it. +- **`vlda-01`'s copy**: left stopped (container not removed, data not + deleted) as a cold backup — reversible if ever needed; not decommissioned + outright. + ### Password vault sync (KeePass, via Nextcloud) Each user's KeePass database now syncs through Nextcloud's own WebDAV diff --git a/SYNC-PLAN.md b/SYNC-PLAN.md index b0bf676..c439f2c 100644 --- a/SYNC-PLAN.md +++ b/SYNC-PLAN.md @@ -47,16 +47,8 @@ outright, so alpha's availability stops depending on vlda-01's. ### 2. Gitea → full migration, not sync -Just repos + a small DB — no reason to keep this tied to vlda-01's uptime. - -- Stop the Gitea container on vlda-01, copy its data volume (repos + DB + - config) to alpha. -- Bring it up on alpha as a permanent container, following the exact - pattern already used for `web`/`cloud.jayfield.org`: publish to - `127.0.0.1:` → Apache vhost (`git.jayfield.org`) → `certbot --apache`. -- Decommission or keep vlda-01's copy as a cold backup, admin's choice. - -**Status: not started. No open questions — ready to build when wanted.** +**Status: done, 2026-07-26 — see `README.md`'s "Gitea" section for the live +setup.** vlda-01's copy left stopped as a cold backup, not decommissioned. ### 3. Jellyfin → scoping question, not yet planned @@ -102,8 +94,7 @@ financial/security stakes. ## Suggested build order -1. Gitea (no open questions, most self-contained, validates the general - "migrate a dockerized service to alpha + Apache vhost" pattern). +1. ~~Gitea~~ — done, see above. 2. Files via Syncthing (validates the intermittent-sync approach before trusting it with anything else). 3. Dogecoin node — **only after explicit sign-off on the wallet-split