diff --git a/docs/deployment.md b/docs/deployment.md index cc42530..c44da70 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -100,12 +100,15 @@ Adding or rotating a user means editing `users.toml` on minerva and restarting the container so the boot-time parser picks up the change: ```bash -ssh minerva.lan -docker run --rm -i doctate-server:latest hash-password # silent prompt, prints hash -nano /opt/stacks/doctate-server/config/users.toml # paste the hash -docker compose -f /opt/stacks/doctate-server/compose.yaml restart doctate-server +ssh minerva.lan 'docker run --rm -i doctate-server:latest hash-password' +ssh minerva.lan 'nano /opt/stacks/doctate-server/config/users.toml' +./scripts/restart-server.sh ``` +`scripts/restart-server.sh` wraps the `docker compose ... restart` plus +a `/api/health` poll, so you see in one line whether the new config is +actually live or whether the server hit a boot-time error. + The `users.toml` mount is read-only by design — the container is not allowed to modify the auth file. Edits happen on the host. @@ -133,7 +136,7 @@ rollback — only the binary swaps. | Login refused on HTTPS | `COOKIE_SECURE` and TLS-proxy mismatch — see "TLS" section below | | File missing inside container | `docker compose -f /opt/stacks/doctate-server/compose.yaml exec doctate-server ls /app` | | Health-check status | `ssh minerva.lan 'docker inspect --format "{{.State.Health.Status}}" doctate-server'` | -| Config edit not picked up | `docker compose ... restart doctate-server` — most config is read on boot, not per request | +| Config edit not picked up | `./scripts/restart-server.sh` — most config is read on boot, not per request | | Stale image tag on minerva | `docker images --filter dangling=true` — retag or `docker image prune` | ## TLS / nginx reverse proxy @@ -145,9 +148,8 @@ to `http://minerva.lan:3000`, set the cookie flag accordingly so browsers actually accept the session cookie: ```bash -ssh minerva.lan -echo 'COOKIE_SECURE=true' >> /opt/stacks/doctate-server/config/.env -docker compose -f /opt/stacks/doctate-server/compose.yaml restart doctate-server +ssh minerva.lan "echo 'COOKIE_SECURE=true' >> /opt/stacks/doctate-server/config/.env" +./scripts/restart-server.sh ``` Without this override under a TLS proxy, the login flow looks like it diff --git a/scripts/restart-server.sh b/scripts/restart-server.sh new file mode 100755 index 0000000..ca2d85b --- /dev/null +++ b/scripts/restart-server.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Restart doctate-server on a remote Docker host (default: minerva.lan). +# Use after editing /opt/stacks/doctate-server/config/{users,settings}.toml +# or .env — the server reads those at boot, not per request. +# +# Usage: ./scripts/restart-server.sh [host] +# host default: minerva.lan +# +# Exit code 0 on healthy server, 1 on health-check timeout. + +set -euo pipefail + +HOST="${1:-minerva.lan}" +REMOTE="/opt/stacks/doctate-server" + +echo ">>> Restarting doctate-server on $HOST" +ssh "$HOST" "docker compose -f $REMOTE/compose.yaml restart doctate-server" + +echo ">>> Waiting for /api/health" +for i in $(seq 1 20); do + if curl -fsS "http://$HOST:3000/api/health" >/dev/null 2>&1; then + echo " OK after ${i} attempt(s)" + curl -s "http://$HOST:3000/api/health" + echo + exit 0 + fi + sleep 2 +done + +echo ">>> TIMEOUT (40s) — last 50 lines of container logs:" >&2 +ssh "$HOST" "docker logs --tail 50 doctate-server" >&2 || true +exit 1