# Application Design (consolidated) — atheos-blog-lxc **Stage**: INCEPTION — Application Design (minimal depth) · **Date**: 2026-09-29 **Deploy target**: Proxmox LXC `136` on node `scotty` (.69) — Alpine 3.23 · LAN-only --- ## 1. What this system is A small, single-purpose guest whose only job is to put a **browser editor** in front of the `armistace/blog` working copy. It is deliberately **not** a build environment. ``` ┌───────────────────────── LXC 136 (scotty) ─────────────────────────┐ Browser (LAN) │ │ http:/// ────┼──► nginx :80 ──unix socket──► php-fpm (php83) ──► Atheos (PHP) │ │ │ │ │ ├──► workspace/blog/** (rw) │ │ └──► git CLI ──► local commit│ └────────────────────────────────────────────────────────────────────┘ │ (operator, later) SSH identity + SSH remote ▼ Gitea git.aridgwayweb.com ``` ## 2. Components | ID | Component | Role | |---|---|---| | C1 | LXC `136` on scotty, Alpine 3.23 | isolated runtime, OpenRC, 20 GB root, onboot | | C2 | nginx :80 | HTTP front end; sends `*.php` to C3 | | C3 | php-fpm `php83` | PHP runtime; ZIP/OPENSSL/MBSTRING; `allow_url_fopen=On` | | C4 | Atheos (pinned SHA) | the editor; git via its `codegit` component | | C5 | `/var/www/atheos/workspace` | project storage (writable) | | C6 | git CLI | VCS; `safe.directory` set; **no identity** (operator-owned) | | C7 | `blog` working copy | clone of `armistace/blog` on `master` | | C8 | Gitea (external) | clone source; agent never pushes | | C9 | Operator (external) | owns SSH key, git identity, Atheos admin, remote switch | ## 3. Key interfaces 1. **nginx → php-fpm**: `fastcgi_pass unix:` must equal the pool's `listen =`. Mismatch ⇒ **502**. 2. **Atheos → filesystem**: writable `config.php`, `data/`, `workspace/`, `plugins/`, `themes/`. Failure ⇒ installer dependency error. 3. **Atheos → git**: needs `git` on PATH **and** `safe.directory` for the workspace (else *dubious ownership*). Identity intentionally unset. 4. **git → Gitea**: HTTPS clone (public); operator later switches to SSH. 5. **OpenRC**: `nginx` + `php-fpm83` enabled at `default` runlevel — otherwise first reboot breaks service (AC-6). ## 4. Design decisions (from the gate) | # | Decision | Source | |---|---|---| | D1 | **No git identity configured by the agent.** `user.name`/`user.email` left unset; RUNBOOK instructs the operator to set them first. | Q1=B | | D2 | **Atheos pinned to a resolved commit SHA**, with an additional **update script** that re-clones at latest and re-pins. | Q2 | | D3 | Web root `/var/www/atheos`; workspace `/var/www/atheos/workspace`; nginx :80; php-fpm via unix socket. | Q3 | | D4 | Atheos served at the **site root**. | assumed, accepted | | D5 | Operator completes Atheos's first-run installer; **agent seeds no users**. | FR-11 / Q2 of requirements | | **D6** | **Credential = a per-repository Gitea deploy key scoped to `armistace/blog`, write-enabled** (`read_only:false`), owned by the php-fpm user, aliased via `~/.ssh/config` with `IdentitiesOnly yes`. **Not** a PAT (account-wide scopes) and **not** a dedicated Gitea user (no blast-radius reduction for `blog`). Private key generated on the guest; public half handed to the operator to add in-repo. | Andrew, 2026-09-29 (security review) | ## 5. Scope guards (each is a testable negative) - No database installed - **No Python / pelican / `make`** — the presence of Python is a defect (AC-8) - No NPM proxy host / DNS / port-forward (FR-10) - No `armistace` credential, SSH key, or git identity created by the agent (FR-11) ## 6. Design-level risks handed to Infrastructure Design - **C-1** Atheos on Alpine is under-documented → resolve the FPM socket and extension package names from the *installed* system, not from upstream docs. - **C-2** OpenRC, not systemd → all service work uses `rc-service` / `rc-update`. - **C-3** Alpine template must be downloaded on scotty first (`pveam update` + `download`). - **C-4** The installer needs a writable web root before it will run. ## 7. Unit mapping U1 guest (C1) · U2 web stack (C2,C3) · U3 Atheos (C4,C5) · U4 git + clone (C6,C7) · U5 docs + script (all)