# Deploying the Tane landing site (tane.comunes.org) Runbook for publishing changes to the landing page. Written so another agent (or a human) can reproduce it without prior context. ## Architecture (what actually runs) ``` browser ── Cloudflare ── assange (nginx reverse proxy, TLS) ── groucho:8082 ── nginx container (static Hugo site) ``` - The site source lives in this repo under `site/` (Hugo). It is **built into a static nginx image on the host** — no Hugo on the control node, no registry. - `site/` builds legal + about pages from `docs/` (single source of truth) and serves screenshots generated by the Flutter golden harness. - **Deploy is automatic**: a Forgejo Actions workflow ([`.forgejo/workflows/site.yml`](../.forgejo/workflows/site.yml)) runs on every push to `main` that touches `site/**` or `docs/**`. It rsyncs `site/` straight to `groucho` over SSH (runner and host share the internal subnet) and rebuilds the Hugo→nginx container — no Ansible run needed for routine content changes. The Ansible playbook below is now only for the one-time proxy/vhost setup and as a manual fallback (e.g. deploying uncommitted work from a worktree). - Two separate git repos are involved: - **Tane repo** (this one): the `site/` source, docs, the screenshot harness, and the `site` deploy workflow. - **Ansible repo**: `~/proyectos/sync/comunes/shared-l2/ansible` — the reverse-proxy vhost, and a manual-deploy fallback playbook. ## One-time setup (already done; only if starting fresh) ```sh cd ~/proyectos/sync/comunes/shared-l2/ansible ansible-galaxy collection install -r collections/requirements.yml # community.docker + ansible.posix # Publish the vhost on the proxy (adds tane.comunes.org). NOT needed for content updates: ansible-playbook -i comunes_inventory.ini proxies.yml --tags proxy-loop ``` DNS `tane.comunes.org` and the `comunes.org` TLS cert (must cover the subdomain) are already in place. ## Routine deploy (the common case) ### 1. Regenerate derived content (only if you changed the sources) Legal / About text (edited under `docs/legal/**`, `docs/que-es-tane.md`, `docs/what-is-tane.md`): ```sh cd /site && ./build-legal.sh # regenerates content/legal/*.md + content/about.*.md ``` Screenshots (edited the harness or want fresh app shots): ```sh cd /apps/app_seeds flutter test --update-goldens --run-skipped --tags screenshots test/screenshots/screenshots_test.dart tool/collect_screenshots.sh # copies PNGs into site/assets/screenshots + fastlane ``` (The OG social cards `site/static/og-*.png` are regenerated by hand when the inventory shot changes — see the `og-tpl.sh` step in git history; optional.) ### 2. Commit & land on main ```sh cd && git add -A && git commit -m "..." git -C ~/proyectos/dev/tane merge --ff-only # land on main git -C ~/proyectos/dev/tane push origin main ``` Pushing to `main` with changes under `site/**` or `docs/**` triggers the `site` Forgejo Actions workflow automatically — nothing else to run. Watch it at `https://git.comunes.org/comunes/tane/actions` (workflow name `site`), or trigger it manually via `workflow_dispatch` if a push didn't touch those paths. ### 3. Verify ```sh curl -sI https://tane.comunes.org/ | head -1 # 200 curl -s https://tane.comunes.org/es/about/ | grep -o '[^<]*' ``` ## Manual deploy fallback (Ansible) Only needed if Forgejo Actions is down, the `GROUCHO_DEPLOY_KEY` secret is missing, or you want to push uncommitted work from a worktree: ```sh cd ~/proyectos/sync/comunes/shared-l2/ansible ansible-playbook -i comunes_inventory.ini tane-landing.yml \ -e tane_site_src=/abs/path/to/worktree/site # omit to use the main checkout ``` This rsyncs `site/` to `groucho:/data/tane-landing/src`, rebuilds the Hugo→nginx image there, and recreates the container. `proxies.yml` does **not** need re-running for content changes. ## Gotchas - **Cloudflare + assange cache static assets ~16 days by stable URL.** The screenshots and CSS are **fingerprinted** (`… | fingerprint` in the Hugo templates), so their URLs change with content and bust the cache automatically. Fixed-URL assets — `og-*.png`, `favicon*`, `site.webmanifest`, `/logo.png` — are NOT fingerprinted: if you change one, either purge Cloudflare or add a `?v=N`. Symptom of a stale asset: `curl ` returns old bytes but `curl ?v=1` returns the new ones, and the container file (`docker exec tane-landing ls -l /usr/share/nginx/html/...`) is already correct. - **Screenshot golden test is skip-by-default** (`dart_test.yaml`), so CI stays green; you must pass `--run-skipped --tags screenshots` to run/update it. - **main can diverge** (other sessions commit to it). If `merge --ff-only` fails, rebase your branch onto main first: `git rebase main` (site changes rarely conflict), then FF. - **`--check` (dry-run) fails at the compose step** ("/data/tane-landing is not a directory") because check mode doesn't create the synced dir — that's expected, not a real error; do a real run. - Container port is **8082** on groucho, bound `0.0.0.0` (firewall restricts it to assange). The proxy vhost lives in `proxies.yml` under `citems` (cert `comunes.org`).