API container writes trigger files to a shared volume (data/upgrade/),
and a systemd path watcher on the host detects them and runs the
upgrade scripts. This avoids giving the container Docker socket access.
- Add upgrade-check.sh (git fetch + compare + write status.json)
- Add upgrade-watcher.sh (systemd bridge, dispatches check/upgrade)
- Add systemd path/service units with placeholder substitution
- Modify upgrade.sh with --api-mode flag (progress.json + result.json)
- Add API upgrade module (service + routes, SUPER_ADMIN only)
- Add System tab to Settings page with version info, changelog,
progress steps, and upgrade confirmation modal
- Add upgrade watcher installation to config.sh wizard
- Add data/upgrade/ shared volume to api service in docker-compose
Bunker Admin
Two issues occurred during upgrades:
1. Gancio config.json lost when Docker volume name prefix changes
(e.g., changemakerlite_ vs changemaker-lite_). Gancio finds existing
DB but no config and enters restart loop. Fix: verify_gancio_config()
checks the volume and regenerates config.json from .env if missing.
2. mkdocs-site-server (LSIO nginx) returns 403 after upgrade because
the anonymous /config volume shadows the ./mkdocs/site bind mount.
Fix: docker compose rm -sf the LSIO container before up -d so the
anonymous volume is recreated fresh.
Also adds Gancio and MkDocs site health checks to Phase 6 verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>