docs(deploy): document update-all.sh as the post-pull orchestrator

Rewrite the routine-redeploy section around update-all.sh (rolling vs --hard),
list the steps it runs, note the python>=3.11 requirement for build-modlist on
cochi (default python3 is 3.10), and that www/ + mods.json are generated every
run. The deploy skill = pull + fetch-authlib + ./update-all.sh --hard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 01:06:39 +02:00
parent 37d21cacf9
commit 220b43d007

View File

@@ -14,48 +14,55 @@ Production host for the Ulicraft stack.
## Routine redeploy
```bash
ssh cochi
cd /home/ubuntu/mc/ulicraft-server-v1
git pull --ff-only
tooling/render-config.sh # re-render drasl/nmsr configs from .env
tooling/sync-server-mods.sh # sync ./server-mods from $DISTRIBUTION_WEB_ROOT
docker compose down --remove-orphans
docker compose up -d --build
```
`update-all.sh` (repo root) is the **single source of truth** for the post-pull
build + restart steps. Run it AFTER a `git pull` (it never pulls or pushes).
Strict halt on any error — never a partial deploy.
Or as a one-shot from your workstation:
Two modes:
- `./update-all.sh`**rolling**: `docker compose up -d --build`, then restart
ONLY the services whose mounted inputs changed since a pre-run snapshot
(drasl/nmsr on a config re-render, minecraft on a mod change). Minimal
downtime. Does **not** detect caddy static-conf (`caddy/conf.d/*.caddy`)
changes — use `--hard` for those.
- `./update-all.sh --hard` — `docker compose down --remove-orphans && up -d
--build`. Full restart (Minecraft world downtime); picks up everything.
One-shot full redeploy from your workstation (the `deploy` skill does exactly
this):
```bash
ssh cochi 'set -e
cd /home/ubuntu/mc/ulicraft-server-v1
git pull --ff-only
tooling/render-config.sh
tooling/sync-server-mods.sh
docker compose down --remove-orphans
docker compose up -d --build'
tooling/fetch-authlib.sh # ensure authlib jar (rarely changes; NOT in update-all)
./update-all.sh --hard'
```
`render-config.sh` re-renders the drasl/nmsr configs from `.env`;
`sync-server-mods.sh` mirrors the `both`/`server` mod subset (from
`mods-sides.json`) out of `$DISTRIBUTION_WEB_ROOT` into `./server-mods` before
the stack comes back up. `$DISTRIBUTION_WEB_ROOT` must resolve on the host (it
also backs the caddy `distribution.` mount).
### Landing rebuild (not part of `compose`)
The landing site (incl. `/register`) is static `www/`, gitignored — a `git pull`
does **not** update it. Rebuild on the host whenever `landing/` changed or you
toggled `REGISTRATION_MODE` (it bakes the invite-field on/off at build, and Drasl's
`RequireInvite` is derived from the same key by `render-config.sh`):
Everyday landing/config tweak (no world downtime):
```bash
( cd landing && set -a && . ../.env && set +a && pnpm run build ) # → www/
docker compose restart drasl # apply CORS / RateLimit / RequireInvite
ssh cochi 'cd /home/ubuntu/mc/ulicraft-server-v1 && git pull --ff-only && ./update-all.sh'
```
`down`/`up` is not needed for a landing-only or flag-only change — rebuild `www/`
and restart `drasl`.
Steps `update-all.sh` runs, in order: `render-config.sh` (drasl/nmsr from `.env`;
halts on a bad `REGISTRATION_MODE`) → `sync-server-mods.sh` (mirror the
`both`/`server` subset from `mods-sides.json` out of `$DISTRIBUTION_WEB_ROOT`
into `./server-mods`) → `build-modlist.py` (regen landing `mods.json` + logos;
**run under `python>=3.11`** — cochi's default `python3` is 3.10, but
`python3.11` is installed and the script auto-selects it) → landing `pnpm build`
(sources nvm + `.env`, never `npm`) → docker compose. `$DISTRIBUTION_WEB_ROOT`
must resolve on the host (it also backs the caddy `distribution.` mount).
### Landing site + mod list (generated, not in git)
Both the static site `www/` AND the landing `mods.json` are gitignored — a `git
pull` never updates them. `update-all.sh` regenerates both every run
(`mods.json` via `build-modlist.py`, `www/` via `pnpm build`). A flag-only
`REGISTRATION_MODE` change just needs a rolling `./update-all.sh`: it rebuilds
`www/` (bakes the invite-field on/off) and restarts `drasl` only if
`render-config.sh` changed its config (Drasl's `RequireInvite`/CORS/RateLimit) —
no world downtime.
## Known host-local divergence on `cochi` (uncommitted)