Use the old static menu directory as the app's data root
That was the intent of the uncommitted edit, and it is a better location than a
second directory: the app inherits the place the menus were already served from
and only ever reads and writes its own data/ and site.env inside it.
app_root is written as /var/lib/{{ host }}, quoted, because the unquoted form is
what failed to parse. Every documented path follows, and the deployment readme
now says that emptying the old menu files means deleting those files rather than
the directory, which holds the live content.
This commit is contained in:
1 parent
65b66f712d
commit
25ef94d7af
4 files changed
+35
-24
No files matched your search
+16
-10
@@ -5,16 +5,22 @@ app's container and points the Site's web address at it. There is no older
|
|||||||
system to keep serving, so there is no staged rollout and nothing to retire —
|
system to keep serving, so there is no staged rollout and nothing to retire —
|
||||||
deploying an earlier tag is the rollback.
|
deploying an earlier tag is the rollback.
|
||||||
|
|
||||||
|
**The app's data root is the directory the old static menus were served from**
|
||||||
|
(`/var/lib/menu.<site>`), on purpose, so the app inherits the location instead of
|
||||||
|
a second one. The app only reads and writes `data/` and `site.env` inside it. If
|
||||||
|
you later want the old menu files gone, delete those files — not the directory,
|
||||||
|
which now holds the live content.
|
||||||
|
|
||||||
## What lives where
|
## What lives where
|
||||||
|
|
||||||
| Thing | Where |
|
| Thing | Where |
|
||||||
| -------------------------------------- | -------------------------------------------------------------------------- |
|
| -------------------------------------- | ---------------------------------------------------------------------- |
|
||||||
| Name, tagline, icon, categories, menus | on the server under `/var/lib/menu-app.<site>/data` — the admin edits them |
|
| Name, tagline, icon, categories, menus | on the server under `/var/lib/menu.<site>/data` — the admin edits them |
|
||||||
| Theme colours | `config/<site>.site.json` in the repo, baked into the image |
|
| Theme colours | `config/<site>.site.json` in the repo, baked into the image |
|
||||||
| Admin password hash, session secret | `/var/lib/menu-app.<site>/site.env` (untracked, mode 600) |
|
| Admin password hash, session secret | `/var/lib/menu.<site>/site.env` (untracked, mode 600) |
|
||||||
| Which image tag runs | `-e tag=<tag>` |
|
| Which image tag runs | `-e tag=<tag>` |
|
||||||
| Which Site is deployed | the inventory entry in `hosts` |
|
| Which Site is deployed | the inventory entry in `hosts` |
|
||||||
| The web address it serves | `host:` in `vars/<site>.yml` |
|
| The web address it serves | `host:` in `vars/<site>.yml` |
|
||||||
|
|
||||||
## Deploying
|
## Deploying
|
||||||
|
|
||||||
@@ -60,13 +66,13 @@ publish something.
|
|||||||
|
|
||||||
## The admin password
|
## The admin password
|
||||||
|
|
||||||
The app starts with the admin disabled while `/var/lib/menu-app.<site>/site.env`
|
The app starts with the admin disabled while `/var/lib/menu.<site>/site.env`
|
||||||
is missing, and the playbook says so rather than failing. Create it once per
|
is missing, and the playbook says so rather than failing. Create it once per
|
||||||
Site:
|
Site:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
scp scripts/provision-site-env.sh monoco:/tmp/
|
scp scripts/provision-site-env.sh monoco:/tmp/
|
||||||
ssh monoco bash /tmp/provision-site-env.sh /var/lib/menu-app.hopsngrains.com
|
ssh monoco bash /tmp/provision-site-env.sh /var/lib/menu.hopsngrains.com
|
||||||
ssh monoco docker restart menu-app.hopsngrains.com
|
ssh monoco docker restart menu-app.hopsngrains.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,9 @@ docker_container: 'menu-app.{{ title }}'
|
|||||||
docker_network: '{{ docker_container }}_net'
|
docker_network: '{{ docker_container }}_net'
|
||||||
|
|
||||||
# Everything the app writes — data/ and the untracked site.env.
|
# Everything the app writes — data/ and the untracked site.env.
|
||||||
app_root: '/var/lib/menu-app.{{ title }}'
|
#
|
||||||
|
# Deliberately the directory the old static menus were served from, so the app
|
||||||
|
# inherits the location rather than a second one. The app only ever reads and
|
||||||
|
# writes its own data/ inside it; the old menu files can be emptied out when
|
||||||
|
# they are no longer wanted, and the directory itself must stay.
|
||||||
|
app_root: '/var/lib/{{ host }}'
|
||||||
+10
-10
@@ -9,9 +9,9 @@ For whoever is on the other end of "the menu is wrong". The design is in
|
|||||||
| Thing | Where |
|
| Thing | Where |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| The app | container `menu-app.<site>` on `monoco`, image `registry.tanshu.com/menu-admin:<tag>` |
|
| The app | container `menu-app.<site>` on `monoco`, image `registry.tanshu.com/menu-admin:<tag>` |
|
||||||
| Menu content | `/var/lib/menu-app.<site>/data` — `originals/`, `drafts/`, `published/` |
|
| Menu content | `/var/lib/menu.<site>/data` — `originals/`, `drafts/`, `published/` |
|
||||||
| Admin | `https://<vhost>/admin` |
|
| Admin | `https://<vhost>/admin` |
|
||||||
| The password | `/var/lib/menu-app.<site>/site.env` (mode 600, never in git) |
|
| The password | `/var/lib/menu.<site>/site.env` (mode 600, never in git) |
|
||||||
| Categories | `data/sections.json`, edited in the admin |
|
| Categories | `data/sections.json`, edited in the admin |
|
||||||
| Brand and theme | `config/<site>.site.json` in this repo, baked into the image (the palette follows the Stitch system in `docs/design/stitch/`) |
|
| Brand and theme | `config/<site>.site.json` in this repo, baked into the image (the palette follows the Stitch system in `docs/design/stitch/`) |
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ open the set you want and press "Make current". Its URL does not change.
|
|||||||
**Change the admin password.** On the server:
|
**Change the admin password.** On the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bash /tmp/provision-site-env.sh /var/lib/menu-app.hopsngrains.com --force
|
bash /tmp/provision-site-env.sh /var/lib/menu.hopsngrains.com --force
|
||||||
docker restart menu-app.hopsngrains.com
|
docker restart menu-app.hopsngrains.com
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ Original survives, the app can rebuild them:
|
|||||||
```sh
|
```sh
|
||||||
docker run --rm --user 1000:1000 -e MENU_ROOT=/data \
|
docker run --rm --user 1000:1000 -e MENU_ROOT=/data \
|
||||||
-e MENU_SITE_CONFIG=/app/config/hopsngrains.site.json \
|
-e MENU_SITE_CONFIG=/app/config/hopsngrains.site.json \
|
||||||
-v /var/lib/menu-app.hopsngrains.com:/data \
|
-v /var/lib/menu.hopsngrains.com:/data \
|
||||||
--entrypoint node registry.tanshu.com/menu-admin:<tag> src/cli/repair.ts
|
--entrypoint node registry.tanshu.com/menu-admin:<tag> src/cli/repair.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ npm run check-site -- https://menu.hopsngrains.com
|
|||||||
## Backups
|
## Backups
|
||||||
|
|
||||||
The app is the only writer. The irreplaceable part is
|
The app is the only writer. The irreplaceable part is
|
||||||
`/var/lib/menu-app.<site>/data/originals` — the photos exactly as uploaded, from
|
`/var/lib/menu.<site>/data/originals` — the photos exactly as uploaded, from
|
||||||
which everything else can be regenerated with `repair`. Back that directory up;
|
which everything else can be regenerated with `repair`. Back that directory up;
|
||||||
`site.env` is worth keeping too (otherwise you re-provision the password).
|
`site.env` is worth keeping too (otherwise you re-provision the password).
|
||||||
|
|
||||||
@@ -107,9 +107,9 @@ For whoever is on the other end of "the menu is wrong". The design is in
|
|||||||
| Thing | Where |
|
| Thing | Where |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| The app | container `menu-app.<site>` on `monoco`, image `registry.tanshu.com/menu-admin:<tag>` |
|
| The app | container `menu-app.<site>` on `monoco`, image `registry.tanshu.com/menu-admin:<tag>` |
|
||||||
| Menu content | `/var/lib/menu-app.<site>/data` — `originals/`, `drafts/`, `published/` |
|
| Menu content | `/var/lib/menu.<site>/data` — `originals/`, `drafts/`, `published/` |
|
||||||
| Admin | `https://<vhost>/admin` |
|
| Admin | `https://<vhost>/admin` |
|
||||||
| The password | `/var/lib/menu-app.<site>/site.env` (mode 600, never in git) |
|
| The password | `/var/lib/menu.<site>/site.env` (mode 600, never in git) |
|
||||||
| Categories | `data/sections.json`, edited in the admin |
|
| Categories | `data/sections.json`, edited in the admin |
|
||||||
| Brand and theme | `config/<site>.site.json` in this repo, baked into the image (the palette follows the Stitch system in `docs/design/stitch/`) |
|
| Brand and theme | `config/<site>.site.json` in this repo, baked into the image (the palette follows the Stitch system in `docs/design/stitch/`) |
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ open the set you want and press "Make current". Its URL does not change.
|
|||||||
**Change the admin password.** On the server:
|
**Change the admin password.** On the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bash /tmp/provision-site-env.sh /var/lib/menu-app.hopsngrains.com --force
|
bash /tmp/provision-site-env.sh /var/lib/menu.hopsngrains.com --force
|
||||||
docker restart menu-app.hopsngrains.com
|
docker restart menu-app.hopsngrains.com
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ Original survives, the app can rebuild them:
|
|||||||
```sh
|
```sh
|
||||||
docker run --rm --user 1000:1000 -e MENU_ROOT=/data \
|
docker run --rm --user 1000:1000 -e MENU_ROOT=/data \
|
||||||
-e MENU_SITE_CONFIG=/app/config/hopsngrains.site.json \
|
-e MENU_SITE_CONFIG=/app/config/hopsngrains.site.json \
|
||||||
-v /var/lib/menu-app.hopsngrains.com:/data \
|
-v /var/lib/menu.hopsngrains.com:/data \
|
||||||
--entrypoint node registry.tanshu.com/menu-admin:<tag> src/cli/repair.ts
|
--entrypoint node registry.tanshu.com/menu-admin:<tag> src/cli/repair.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ npm run check-site -- https://menu.hopsngrains.com
|
|||||||
## Backups
|
## Backups
|
||||||
|
|
||||||
The app is the only writer. The irreplaceable part is
|
The app is the only writer. The irreplaceable part is
|
||||||
`/var/lib/menu-app.<site>/data/originals` — the photos exactly as uploaded, from
|
`/var/lib/menu.<site>/data/originals` — the photos exactly as uploaded, from
|
||||||
which everything else can be regenerated with `repair`. Back that directory up;
|
which everything else can be regenerated with `repair`. Back that directory up;
|
||||||
`site.env` is worth keeping too (otherwise you re-provision the password).
|
`site.env` is worth keeping too (otherwise you re-provision the password).
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -45,7 +45,7 @@ caddy (80/443, TLS) ──reverse_proxy──▶ menu-app.hopsngrains.com:3000
|
|||||||
### Storage
|
### Storage
|
||||||
|
|
||||||
```
|
```
|
||||||
/var/lib/menu-app.hopsngrains.com/
|
/var/lib/menu.hopsngrains.com/
|
||||||
├── site.env # ADMIN_PASSWORD_HASH, SESSION_SECRET (mode 600, untracked)
|
├── site.env # ADMIN_PASSWORD_HASH, SESSION_SECRET (mode 600, untracked)
|
||||||
└── data/
|
└── data/
|
||||||
├── originals/<section>/<set-id>/<page-id>.<hash>.<ext> # never served
|
├── originals/<section>/<set-id>/<page-id>.<hash>.<ext> # never served
|
||||||
@@ -116,9 +116,9 @@ The look is the Atelier Dining & Hospitality system from Stitch (`docs/design/st
|
|||||||
- The container is `node:24-alpine` running TypeScript directly, so there is no build step; sharp's musl binaries come from `npm ci` on the image's own platform. It writes only under `MENU_ROOT` and healthchecks its own `/healthz`.
|
- The container is `node:24-alpine` running TypeScript directly, so there is no build step; sharp's musl binaries come from `npm ci` on the image's own platform. It writes only under `MENU_ROOT` and healthchecks its own `/healthz`.
|
||||||
- The design system is documented in `docs/design/stitch/atelier-dining-hospitality.md`, with the four screens Stitch produced beside it. `config/<site>.site.json` holds the theme and the seed for everything the owner can change: it seeds `data/sections.json` (ADR 0007) and `data/site.json`, which holds the name, tagline, icon and date switch (ADR 0008). Colours stay in the config, so changing them is a rebuild; nothing else does.
|
- The design system is documented in `docs/design/stitch/atelier-dining-hospitality.md`, with the four screens Stitch produced beside it. `config/<site>.site.json` holds the theme and the seed for everything the owner can change: it seeds `data/sections.json` (ADR 0007) and `data/site.json`, which holds the name, tagline, icon and date switch (ADR 0008). Colours stay in the config, so changing them is a rebuild; nothing else does.
|
||||||
- Build locally and push `registry.tanshu.com/menu-admin:<tag>`, matching the sibling `deploy.sh` / `make build-production TAG=` convention.
|
- Build locally and push `registry.tanshu.com/menu-admin:<tag>`, matching the sibling `deploy.sh` / `make build-production TAG=` convention.
|
||||||
- New `menu-admin` playbook in `ansible-playbooks` with per-Site vars (`vars/hopsngrains.yml` first, the other two stubbed): roles `network`, `menu-app` (pull image, create `/var/lib/menu-app.<site>`, start container, health check, then `verify` the data directory) and `caddy` (snippet upsert).
|
- New `menu-admin` playbook in `ansible-playbooks` with per-Site vars (`vars/hopsngrains.yml` first, the other two stubbed): roles `network`, `menu-app` (pull image, create `/var/lib/menu.<site>`, start container, health check, then `verify` the data directory) and `caddy` (snippet upsert).
|
||||||
- The existing `roles/caddy` only *adds* a snippet when its exact text is missing, which cannot change a proxy target; the new playbook's role uses a stable marker so `blockinfile` updates in place, and removes the old role's per-hostname marker at cutover so Caddy never holds two blocks for one hostname.
|
- The existing `roles/caddy` only *adds* a snippet when its exact text is missing, which cannot change a proxy target; the new playbook's role uses a stable marker so `blockinfile` updates in place, and removes the old role's per-hostname marker at cutover so Caddy never holds two blocks for one hostname.
|
||||||
- One-time human step on the server: a `scripts/provision-site-env.sh` prompts for the admin password, hashes it with the image's own hasher, and writes `/var/lib/menu-app.<site>/site.env` (mode 600, never in git). Until it exists the admin is disabled and the public menu still serves.
|
- One-time human step on the server: a `scripts/provision-site-env.sh` prompts for the admin password, hashes it with the image's own hasher, and writes `/var/lib/menu.<site>/site.env` (mode 600, never in git). Until it exists the admin is disabled and the public menu still serves.
|
||||||
- A small CLI: `verify` reports integrity problems in the data directory, `repair` regenerates missing variants from the Originals.
|
- A small CLI: `verify` reports integrity problems in the data directory, `repair` regenerates missing variants from the Originals.
|
||||||
|
|
||||||
## Sequence
|
## Sequence
|
||||||
|
|||||||
Reference in new issue
Block a user