diff --git a/23may2026-Q-server-prototype.md b/23may2026-Q-server-prototype.md deleted file mode 120000 index 78ddde6..0000000 --- a/23may2026-Q-server-prototype.md +++ /dev/null @@ -1 +0,0 @@ -/home/allan/Raspen/Raspxfer/AI-tx/23may2026-Q-server-prototype.md \ No newline at end of file diff --git a/23may2026-Q-server-prototype.md b/23may2026-Q-server-prototype.md new file mode 100644 index 0000000..4a31ad4 --- /dev/null +++ b/23may2026-Q-server-prototype.md @@ -0,0 +1,128 @@ +Project "selfhosted2", 23may2026 + +# Technical environment + +Cross-development environment for prototyping a residential application server behind a VPS-style reverse proxy. + +`hector`: The development machine. ASUS laptop running Linux Mint Mate. The machine on which this LLM session takes place (**Session ID:** ses_21ab382baffej8OpnTkrmaG5UA). + +`agge`: Target machine acting as the 'Q Server'. Dell Optiplex mini PC running a headless Ubuntu Server. This is where the production apps reside. LAN IP `192.168.1.188`, WireGuard IP `10.0.0.2`. + +`raspen`: Target machine acting as a VPS, with a reverse proxy routing all external traffic to applications on `agge` over an encrypted WireGuard tunnel. Raspberry Pi 5, running a headless Raspberry Pi OS Lite (64-bit). LAN IP `192.168.1.187`, WireGuard IP `10.0.0.1`. + +The machines are connected through a dedicated local wifi hotspot, SSID `NR-24`. In the production deployment, `raspen` will be replaced by a cloud VPS with a public IP; the Docker compose and nginx configuration are designed to be portable as-is. + +# Architecture + +``` +hector + │ + └──→ raspen.home (192.168.1.187) ← nginx reverse proxy (Docker) + │ wireguard sidecar (Docker) + │ wg0: 10.0.0.1/30 + │ + │ ────────── WireGuard tunnel ────────── + │ + │ wg0: 10.0.0.2/30 + │ Docker: Gitea, Nextcloud, PostgreSQL + └──→ agge (192.168.1.188) +``` + +Raspen is the single entry point for all traffic. Nginx terminates SSL and proxies requests through the encrypted WireGuard tunnel to agge. No services are exposed on the plain LAN — Docker containers on agge bind exclusively to `10.0.0.2`. + +# Network + +Hosts file on `hector` (`/etc/hosts`): + +``` +192.168.1.187 raspen.home nc.home git.home pg.home +192.168.1.188 agge +``` + +Only `raspen.home`'s IP is published to clients. `agge` has no direct domain mapping in the hosts file (it is addressed only by its WireGuard IP). + +## WireGuard VPN + +| Peer | Interface | IP | Port | +|------|-----------|-----|------| +| raspen | wg0 | 10.0.0.1/30 | ephemeral (outbound) | +| agge | wg0 | 10.0.0.2/30 | 51820/udp | + +Raspen runs WireGuard inside a Docker sidecar container (`linuxserver/wireguard`). Agge runs WireGuard as a native systemd service (`wg-quick@wg0`). UFW on agge allows UDP 51820 inbound. + +Raspen's config (repo: `vps/wireguard/wg_confs/wg0.conf`): +- Connects to `192.168.1.188:51820` +- Keepalive 25s +- Only routes `10.0.0.2/32` through the tunnel + +Agge's config (`/etc/wireguard/wg0.conf`): +- Listens on port 51820 +- Only accepts traffic from `10.0.0.1/32` + +# Applications + +## VPS (raspen) — Docker stack + +Location: `vps/docker-compose.yml` + +Two containers sharing a network namespace: + +- **wireguard**: Creates the VPN tunnel. Publishes ports 80, 443, 5432, 2222, and 51820/udp. +- **nginx**: Reverse proxy. Shares wireguard's network namespace (`network_mode: "service:wireguard"`). Proxies to agge via WireGuard IPs. + +Nginx config (`vps/nginx/conf.d/default.conf`): +- `nc.home:443` → `10.0.0.2:8080` (Nextcloud) +- `git.home:443` → `10.0.0.2:3000` (Gitea) +- `raspen.home:80/443` → static page +- HTTP redirects to HTTPS +- Self-signed SSL certs at `vps/ssl/` + +TCP stream proxies (`vps/nginx/stream.d/`): +- `pg.home:5432` → `10.0.0.2:5432` (PostgreSQL) +- `git.home:2222` → `10.0.0.2:2222` (Gitea SSH) + +## Backend (agge) — Docker stack + +Location: `backend/docker-compose.yml` + +Four containers on an internal `backend` bridge network: + +| Container | Image | Ports (bound to 10.0.0.2) | Purpose | +|-----------|-------|---------------------------|---------| +| postgres | postgres:16-alpine | — (internal) | Database for Nextcloud | +| nextcloud | nextcloud:latest | 8080:80 | File sync & share | +| gitea | gitea/gitea:latest | 3000:3000 (HTTP), 2222:22 (SSH) | Git hosting | +| postgres_remote | postgres:16-alpine | 5432:5432 | Remote-access DB | + +All published ports bind to `10.0.0.2` only, making them inaccessible over the plain LAN — traffic must arrive via the WireGuard tunnel. + +Environment variables are loaded from `.env` (repo root). + +# Development + +Working directory: `/home/allan/Work/selfhosted2`, a Git repo hosted on Gitea at `agge`. Two remote URLs are configured: +- `https://git.home/scoot/selfhosted2.git` (via raspen proxy — useful for read-only with self-signed cert) +- `ssh://git@git.home:2222/scoot/selfhosted2.git` (via raspen stream proxy — used for push) + +Remote access: +- `raspen`: `rasput@192.168.1.187` +- `agge`: `tebarbi@192.168.1.188` + +opencode configuration (`opencode.json`): +- Permission model asks before executing bash or accessing external directories. + +# Session history + +**Session ses_21ab382baffej8OpnTkrmaG5UA** — initial prototype deployment: Docker files written, containers configured, applications deployed and verified. + +**Post-migration recovery** (this session): +1. Hector was rebuilt from Omarchy Linux to Linux Mint Mate, losing the local work directory and self-signed certs. +2. The remote Gitea repo on agge was intact; the local repo was recovered via `GIT_SSL_NO_VERIFY=1 git fetch` over HTTPS (self-signed cert). +3. `/etc/hosts` was corrected — all domains now point to raspen (192.168.1.187) as the single entry point. +4. A WireGuard VPN was established between raspen (Docker sidecar) and agge (native systemd service). +5. Nginx upstream targets were changed from `192.168.1.188` to `10.0.0.2`. +6. Docker port bindings on agge were restricted to `10.0.0.2` to enforce tunnel-only access. +7. UFW on agge was configured to allow WireGuard UDP 51820. +8. Gitea SSH port 2222 was added to nginx's TCP stream proxies on raspen, enabling git push over SSH through the VPN tunnel. + +All services confirmed operational: Gitea (HTTP 200), Nextcloud (HTTP 302), PostgreSQL (port open), and static page (HTTP 200).