From de5ba478346998834ef3114eb706136a52f1ffed Mon Sep 17 00:00:00 2001 From: cyph3rasi Date: Wed, 15 Jul 2026 00:51:19 -0700 Subject: [PATCH] Serve a branded maintenance page while automatic updates rebuild Synapsis Hop-State: A_06FP9GHXYJ7YFGJ8MPGCRRG Hop-Proposal: R_06FP9GGM02EZ1XD9K4DPQ28 Hop-Task: T_06FP9G1KCRT11HM63FWG190 Hop-Attempt: AT_06FP9G1KCTJKQ4EHESDM798 --- README.md | 2 + deploy/install.sh | 1 + deploy/maintenance-server.mjs | 64 +++++++++++++++++++++++++++++ deploy/synapsis-maintenance.service | 20 +++++++++ deploy/uninstall.sh | 2 + deploy/update.sh | 12 +++++- 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 deploy/maintenance-server.mjs create mode 100644 deploy/synapsis-maintenance.service diff --git a/README.md b/README.md index 44d662a..87282ea 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ The installer creates: Every node checks `origin/main` about once per minute. When a new commit is available, Synapsis fast-forwards the checkout, replaces the single `backups/latest` database snapshot, installs dependencies, runs migrations, builds, and restarts automatically. The repository commit count is shown in the Network Info card; `/api/version` exposes both that number and the full deployed commit hash. +While an update is being installed, `synapsis-maintenance.service` temporarily serves a branded maintenance page on the node's configured `PORT`. Existing reverse proxies continue receiving an HTTP response instead of showing a gateway error, and browsers automatically reload when Synapsis is ready. + For a node installed before automatic updates existed, bootstrap the timer once with: ```bash diff --git a/deploy/install.sh b/deploy/install.sh index c38484a..6994df1 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -59,6 +59,7 @@ runuser -u synapsis -- npm --prefix "$APP_DIR" run db:migrate runuser -u synapsis -- npm --prefix "$APP_DIR" run build install -m 0644 "$APP_DIR/deploy/synapsis.service" /etc/systemd/system/synapsis.service +install -m 0644 "$APP_DIR/deploy/synapsis-maintenance.service" /etc/systemd/system/synapsis-maintenance.service install -m 0644 "$APP_DIR/deploy/synapsis-update.service" /etc/systemd/system/synapsis-update.service install -m 0644 "$APP_DIR/deploy/synapsis-update.timer" /etc/systemd/system/synapsis-update.timer runuser -u synapsis -- git -C "$APP_DIR" rev-parse HEAD | install -m 0644 -o synapsis -g synapsis /dev/stdin "$DATA_DIR/deployed-commit" diff --git a/deploy/maintenance-server.mjs b/deploy/maintenance-server.mjs new file mode 100644 index 0000000..264a535 --- /dev/null +++ b/deploy/maintenance-server.mjs @@ -0,0 +1,64 @@ +import http from 'node:http'; + +const host = process.env.MAINTENANCE_HOST || '127.0.0.1'; +const port = Number.parseInt(process.env.PORT || '43821', 10); + +const page = ` + + + + + + Update in progress + + + +
+ +

Update in progress

+

We’re making Synapsis better. We’ll be right back!

+
Checking for the node…
+
+ + +`; + +const server = http.createServer((request, response) => { + response.writeHead(503, { + 'Content-Type': 'text/html; charset=utf-8', + 'Content-Length': Buffer.byteLength(page), + 'Cache-Control': 'no-store, max-age=0', + 'Retry-After': '30', + 'X-Robots-Tag': 'noindex', + }); + if (request.method === 'HEAD') response.end(); + else response.end(page); +}); + +server.listen(port, host, () => { + console.log(`Synapsis maintenance page listening on http://${host}:${port}`); +}); + +const shutdown = () => server.close(() => process.exit(0)); +process.on('SIGINT', shutdown); +process.on('SIGTERM', shutdown); diff --git a/deploy/synapsis-maintenance.service b/deploy/synapsis-maintenance.service new file mode 100644 index 0000000..e05c92a --- /dev/null +++ b/deploy/synapsis-maintenance.service @@ -0,0 +1,20 @@ +[Unit] +Description=Synapsis update maintenance page +After=network-online.target +Wants=network-online.target +Conflicts=synapsis.service + +[Service] +Type=simple +User=synapsis +Group=synapsis +WorkingDirectory=/opt/synapsis +EnvironmentFile=/etc/synapsis.env +ExecStart=/usr/bin/env node /opt/synapsis/deploy/maintenance-server.mjs +Restart=on-failure +RestartSec=1 +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true + diff --git a/deploy/uninstall.sh b/deploy/uninstall.sh index 97f3db5..7eacc46 100755 --- a/deploy/uninstall.sh +++ b/deploy/uninstall.sh @@ -12,8 +12,10 @@ fi systemctl disable --now synapsis-update.timer 2>/dev/null || true systemctl stop synapsis-update.service 2>/dev/null || true +systemctl stop synapsis-maintenance.service 2>/dev/null || true systemctl disable --now synapsis 2>/dev/null || true rm -f /etc/systemd/system/synapsis.service \ + /etc/systemd/system/synapsis-maintenance.service \ /etc/systemd/system/synapsis-update.service \ /etc/systemd/system/synapsis-update.timer systemctl daemon-reload diff --git a/deploy/update.sh b/deploy/update.sh index bcd0201..f2ed94b 100755 --- a/deploy/update.sh +++ b/deploy/update.sh @@ -21,7 +21,7 @@ set +a install_update_units() { units_changed=0 - for unit in synapsis.service synapsis-update.service synapsis-update.timer; do + for unit in synapsis.service synapsis-maintenance.service synapsis-update.service synapsis-update.timer; do if ! cmp -s "$APP_DIR/deploy/$unit" "/etc/systemd/system/$unit"; then install -m 0644 "$APP_DIR/deploy/$unit" "/etc/systemd/system/$unit" units_changed=1 @@ -66,8 +66,15 @@ if [[ "${SYNAPSIS_APPLY_UPDATE:-0}" != "1" ]]; then exec env SYNAPSIS_APPLY_UPDATE=1 APP_DIR="$APP_DIR" DATA_DIR="$DATA_DIR" ENV_FILE="$ENV_FILE" BRANCH="$BRANCH" bash "$APP_DIR/deploy/update.sh" fi +install_update_units systemctl stop synapsis -trap 'systemctl start synapsis' EXIT +systemctl start synapsis-maintenance + +restore_service() { + systemctl stop synapsis-maintenance 2>/dev/null || true + systemctl start synapsis +} +trap restore_service EXIT if [[ -f "${DATABASE_PATH:-$DATA_DIR/synapsis.db}" ]]; then database_file="${DATABASE_PATH:-$DATA_DIR/synapsis.db}" @@ -96,6 +103,7 @@ runuser -u synapsis -- npm --prefix "$APP_DIR" run build deployed_commit="$(runuser -u synapsis -- git -C "$APP_DIR" rev-parse HEAD)" printf '%s\n' "$deployed_commit" | install -m 0644 -o synapsis -g synapsis /dev/stdin "$DEPLOYED_COMMIT_FILE" install_update_units +systemctl stop synapsis-maintenance systemctl start synapsis trap - EXIT echo "Synapsis updated successfully to ${deployed_commit:0:7}."