# menu-admin playbook Deploys the menu app for one Site, beside the existing nginx container at first and in place of it after cutover. Copy this directory to `ansible-playbooks/menu-admin/` and run it from there, so `playbook_dir` and the inventory match the other playbooks. This playbook owns the `menu-app` container and the Site's snippet in the shared Caddyfile. It does not touch the app's source, the image, or the other Sites' containers. ## What lives where | Thing | Where | | --- | --- | | Sections, brand, theme | `config/.site.json` in the app repo, baked into the image | | Menu content, Drafts, Originals | `/var/lib/menu-app./data` on the host | | Admin password hash, session secret | `/var/lib/menu-app./site.env` (untracked, mode 600) | | Which image tag runs | `-e tag=` | Sections are deliberately not editable on the server: changing them is a commit to the app repo, a new image, and a redeploy (ADR 0005). ## Deploying ```sh # 1. Build and push from the app repo ./deploy.sh 2026-09-22 # -> registry.tanshu.com/menu-admin:2026-09-22 # 2. First run: a temporary hostname, so the live site keeps serving ansible-playbook -l monoco -e site=hopsngrains -e tag=2026-09-22 playbook.yml # 3. The admin needs a password before it can be used ssh monoco scripts/provision-site-env.sh /var/lib/menu-app.hopsngrains.com ``` The first run creates `/var/lib/menu-app.hopsngrains.com`, starts the container on the `menu-app.hopsngrains.com_net` network, adds a snippet for `menu-new.hopsngrains.com` to the shared Caddyfile, and reloads Caddy. The existing `menu.hopsngrains.com` vhost still points at the old nginx container. `site.env` is deliberately not created by Ansible: the password is typed by a human on the server. Until it exists the admin is disabled and the playbook says so — the public menu still serves. ## Checking the parallel run From a phone on restaurant wifi, not from the server: - `https://menu-new.hopsngrains.com/` lists the Sections that have a current menu. - A Section page scrolls, the pour line tracks, tapping a page opens it full width. - The admin signs in, uploads a real photo, reorders, previews, publishes. - After publishing, the phone shows the new menu and the old set appears under "Older menus". ## Cutover ```sh ansible-playbook -l monoco -e site=hopsngrains -e tag=2026-09-22 \ -e vhost=menu.hopsngrains.com \ -e retire_nginx_snippet=true \ -e retire_nginx_container=true \ playbook.yml ``` This repoints the real vhost at the app, removes the snippet the old playbook wrote for that hostname, and stops the old container. The old container and `/var/lib/menu.hopsngrains.com` are kept, not deleted: deleting 319 MB of the only copy of the old menus is a human decision, made a week later, once the new site has been trusted. ## Rolling back ```sh docker start nginx-menu.hopsngrains.com ansible-playbook -l monoco -e site=hopsngrains -e tag= \ -e vhost=menu.hopsngrains.com -e retire_nginx_snippet=false playbook.yml ``` Then delete the app's snippet from `/var/lib/caddy/conf/Caddyfile` by hand, or set `vhost` back to the temporary name, and reload Caddy.