Operate / System Ops

Staged upgrades and rollback

The native updater no longer resets the live checkout, clears stashes or removes its dist directory. scripts/deploy.sh invokes the Linux/root-only release helper. It fetches main without modifying working files, extracts a versioned stage as the service account, installs dependencies, runs isolated tests, builds assets and runs production smoke checks before activation. Tests use a separate data directory, never the operator's monitoring database.

Validated releases link the shared root .env/data directory. A systemd drop-in runs current/src/start.js; current is switched with an atomic symlink rename. The helper restarts the service and gates on readiness plus authenticated persistence health for durable releases. If readiness fails it restores the prior pointer and restarts the previous process. A flushed journal records the previous path before activation; the next invocation recovers an interrupted upgrade. Old assets and data are kept intact. A release revision file prevents version checks from reporting the original checkout's stale commit after deployment.

This targets Ubuntu/systemd and assumes the service account already has access to the repository and required Node/npm binaries. A custom port requires READINESS_URL. The helper requires a readable .env with APP_PASSWORD for the persistence gate. SQLite version 1 is additive; future incompatible schema rollback requires a data backup. The helper refuses targets outside the release root and does not delete release directories or shared data. Old stages may be manually cleaned after verifying rollback/backup needs.

CI runs Linux pointer/build-failure/path-boundary tests and a real production-process fixture for successful activation, injected readiness failure, previous-process restoration, journal recovery and shared-data/asset preservation. Windows skips the three Linux symlink tests. No live server or native systemd service has been upgraded by this agent; actual installer/account/sudoers and host-specific unit configuration remain deployment verification work. Container deployments continue to use immutable images and persistent volumes rather than this native helper.

Dashboard updater launch

Production smoke checks wait up to 45 seconds for the first healthy system snapshot after HTTP liveness. An initial 503 is expected while collection is running; authentication failures, malformed snapshots, and unhealthy successful responses still fail validation. A collector that never becomes ready fails with a bounded timeout and its last state.

The installer and updated release helper validate a separate /etc/sudoers.d/system-ops-update policy with visudo before installing it as root with mode 0440. This permits only the exact background deploy command and preserves other sudo rules. An installation bootstrapping through an older release helper needs the one-time command below after its first successful SSH deployment. It uses the fixed root checkout path, not the versioned current path:

sudo env INSTALL_DIR=/opt/system-ops OPS_USER=ops node /opt/system-ops/current/scripts/setup-update-permissions.js

Use the actual install root and service account for a custom installation. This command only repairs the updater permission; it does not start a deployment.

The dashboard invokes the exact permitted sudo command, using noninteractive sudo and the deploy wrapper background mode. The wrapper starts system-ops-update.service outside the dashboard service control group, so restarting the dashboard cannot kill the updater. The worker appends to shared update.log and atomically records an ops-readable update-result.json after readiness/rollback. A short launch grace period avoids reporting failure before systemd has created the unit. Root checkout and active release paths are distinct, so updates remain supported after the first staged activation. Docker/Windows installs are reported as unsupported for dashboard self-update.

Existing broken dashboard installations need a one-time SSH update: from the root checkout run sudo bash scripts/deploy.sh. After the repaired version is installed, dashboard updates use the independent worker. This bypasses the old API launcher without resetting the checkout or deleting assets. Native sudoers/systemd behavior still needs verification on the target server; no live host was modified here. When bootstrapping from an older staged-release helper, also refresh the fixed root wrapper after the first successful SSH update: sudo install -o root -g root -m 755 /opt/system-ops/current/scripts/deploy.sh /opt/system-ops/scripts/deploy.sh (adjust the root for a custom installation). Older helpers do not perform this step automatically. The repaired helper refreshes that wrapper after every subsequent healthy activation.