diff --git a/deploy/README.md b/deploy/README.md index 1b85797..c91a7a6 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -95,19 +95,40 @@ The button is opt-in, and the reason is a boundary rather than caution: INSTALL_UPDATE_HELPER=1 SITE_HOST=chat.example ./deploy/install.sh ``` -That installs `lembas-update.path` and `lembas-update.service`. The web +That installs `lembas-update.path` and `lembas-update.service`, and puts a +**root-owned copy** of `update.sh` at `/usr/local/lib/lembas/update.sh`. The web interface writes `$PREFIX/data/update-requested`; the path unit notices and the -service runs `update.sh` **as root**, on the configured channel. +service runs that copy **as root**, on the configured channel. + +**Why a copy.** The unit used to point inside the checkout, and `install.sh` +clones the checkout *as the service user* — so root was executing a file the +unprivileged account could rewrite, and one that every update replaces with +whatever the branch contained. Either turns a compromise of the web application +into root, and the second needs no compromise at all. The cost is that changing +`update.sh` needs the installer re-run; the script tells you when its copy has +fallen behind, and says so loudly if it finds itself running from inside the +checkout. + +**If you installed the helper before 1.0.0, re-run the installer.** The old +wiring stays until you do, and the update button cannot fix it — the button runs +the old unit. **What that grants.** Anybody who can administer this web interface can then deploy whatever is on the configured branch and restart the service. That is the point of it, and it is why it is not the default. **What it deliberately does not grant.** The request file carries nothing that -reaches a command line — no ref, no branch, no channel, no arguments. Both are -baked into the unit at install time, so the button is always "deploy the channel -this host was configured with" and never "deploy something else". Re-running the installer without the flag removes both units and the -marker, and the page goes back to printing the manual command. +reaches a command line — no ref, no branch, no channel, no arguments, and its +*contents* are never read at all. Both are baked into the unit at install time, +so the button is always "deploy the channel this host was configured with" and +never "deploy something else". Re-running the installer without the flag removes +both units, the marker and the root-owned copy, and the page goes back to +printing the manual command. + +A re-run **keeps the channel this host already follows** rather than resetting it +to `stable`: the channel is declared in `lembas.env` and in the unit, a re-run +keeps the first while rewriting the second, and an installer that silently moved +one half was causing exactly the mismatch the Updates page detects. Without the helper the page says so and shows `sudo …/deploy/update.sh`, which is the same honest degradation the SSH and search extras have.