Skip to content

Upgrade, rollback and repair

MAIA Plus is updated only as a complete signed package, and only through the maintenance utility — MAIA-MAINTENANCE.exe on Windows, maia-maintenance-linux on Linux. There is no separate updater service, and no supported way to replace a live binary, the WebUI build or a migration file by hand. This page describes one update cycle, the Windows and Linux form of every command, and what happens when it fails.

verify signature → preflight (read-only) → pg_dump when migrations are pending
→ atomic switch current/previous → restart service → health gate
→ success, or automatic rollback

Each step exists for a reason:

StepWhy it cannot be skipped
Signature checkProves the package is the one that was built and published
PreflightValidates service configuration, PostgreSQL tools and connectivity, the migration ledger, the backup directory and the health endpoint without touching anything
Verified pg_dumpOnly runs when pendingCount > 0; a database change without a dump cannot be rolled back
Atomic switchcurrent becomes the new payload, the old one moves to previous; nothing is edited in place
Health gatehttp://127.0.0.1:3000/api/v1/status must return 200
State filestate/maintenance-update.json records what happened, for the next person

The procedure is identical; the paths, the shell and the service manager are not.

WindowsLinux
Maintenance utilityMAIA-MAINTENANCE.exemaia-maintenance-linux
Install rootThe directory chosen at install, typically C:\MAIA/opt/maia
Managed serviceNSSM service, default name MAIA; a native sc.exe service is also detectedmaia.service (systemd)
Driver selection--service-driver auto detects NSSM versus native--service-driver auto detects systemd
ElevationPowerShell started with Run as administratorsudo
Backup directoryD:\MAIA-Backups\<date>/var/backups/maia/<date>
Guided scripts in the packageinstall.bat, update.batupdate.sh

--backup-dir must be a persistent directory with free space — not the install root, not a temporary folder. --service-driver auto is the right default; name the driver explicitly only when auto-detection picks the wrong one.

  • Maintenance window — --confirm stops the service, so the restart is a planned outage.
  • Elevated shell — the update starts and stops a service.
  • Install root and service name exactly as the running installation uses them. A wrong service name blocks the preflight rather than guessing.
  • Durable backup directory with free space, outside the install root.
  • pg_dump and pg_restore — assume they are not on PATH. Pass absolute paths with --pg-dump and --pg-restore; on Windows this is the normal case, not the exception.
  • The new signed ZIP extracted outside the live root, into a fresh directory.
Terminal window
cd D:\MAIA-Releases\1.1.1
.\MAIA-MAINTENANCE.exe check --package .

check reads the manifest, the signature and the payload checksums. It prints Verified release <id>. and changes nothing; a failure here means the archive is incomplete or was modified, so re-download it instead of continuing.

It ends in READY TO UPDATE or UPDATE BLOCKED with a reason.

Terminal window
.\MAIA-MAINTENANCE.exe update `
--package . `
--install-root C:\MAIA `
--service MAIA `
--service-driver auto `
--backup-dir D:\MAIA-Backups\2026-11-03

The preflight verifies the service configuration, the PostgreSQL client tools, database connectivity, the migration ledger, the backup directory and the health endpoint. Nothing is written: no file, no database row, no service state, no backup.

An installation that is not managed as a service is updated with --no-service; the tool then refuses to verify the process is down, so a confirmed run additionally requires --manual-service-acknowledgement.

The dump is what makes a rollback possible, so the preflight refuses to continue when it cannot find pg_dump. Do not rely on PATH. A Windows host almost never has PostgreSQL client tools on it, and a working installation is not the same thing as a discoverable one — pass both paths explicitly in the preflight and in the confirmed run:

Terminal window
# All-in-One installer: PostgreSQL lives in the prerequisites root
.\MAIA-MAINTENANCE.exe update `
--package . `
--install-root C:\MAIA `
--service MAIA `
--backup-dir D:\MAIA-Backups\2026-11-03 `
--pg-dump "C:\MAIA-Prerequisites\pgsql\bin\pg_dump.exe" `
--pg-restore "C:\MAIA-Prerequisites\pgsql\bin\pg_restore.exe"
Terminal window
# Standalone PostgreSQL 18 installed with its own installer
.\MAIA-MAINTENANCE.exe update `
--package . `
--install-root C:\MAIA `
--service MAIA `
--backup-dir D:\MAIA-Backups\2026-11-03 `
--pg-dump "C:\Program Files\PostgreSQL\18\bin\pg_dump.exe" `
--pg-restore "C:\Program Files\PostgreSQL\18\bin\pg_restore.exe"

Use binaries of at least the server’s major version. pg_dump aborts when the server is newer than itself, and pg_restore refuses a dump format it does not recognise — so an old client copied from another host turns a valid backup into a blocked preflight. When the database runs in a container or on another host, the tools still run on the MAIA host: install a matching client there instead of loosening the check.

Only when the preflight says READY, confirm. --confirm performs, in order: the verified dump (only when migrations are pending), the atomic switch, the service registration update, the restart, and the health gate.

Terminal window
.\MAIA-MAINTENANCE.exe update --confirm `
--package . `
--install-root C:\MAIA `
--service MAIA `
--service-driver auto `
--backup-dir D:\MAIA-Backups\2026-11-03

The package also ships update.bat for operators who prefer not to assemble the command line. Run it with Run as administrator: it asks for the install root and the service name, runs the read-only preflight, and applies the update only after you type UPDATE. With --no-service it asks only for that typed confirmation and supplies --manual-service-acknowledgement for you — the tool cannot verify the process is down, so the acknowledgement is the operator’s, not the script’s. install.bat follows the same shape for a first installation, ending at the WebUI Setup Wizard.

On Linux, update.sh wraps the same call with --confirm: it requires root, --install-root and either --service <name> or --no-service, and asks for UPDATE — plus MANUAL when the service is not managed.

The scripts are wrappers, not a different mechanism — they call the same MAIA-MAINTENANCE.exe update shown above, so a blocked preflight blocks the script too.

The update is complete only when the health gate passes and the state file records COMMITTED. Every other ending requires interpretation.

stageMeaningWhat it proves
COMMITTEDUpdate finished and the health gate passedThe new build is serving
FAILEDThe update failed; automatic rollback is startingNothing yet — rollback has not been evaluated
ROLLED_BACKAutomatic rollback completed without collected failuresThe previous build is serving again
INTERRUPTEDThe process died, or the recorded state was unreadableUnknown — inspect current/, previous/ and the dump
recovery_required (legacy state file)At least one rollback step failedManual recovery with the recorded backup — see When it fails

FAILED is not a verdict on rollback, and ROLLED_BACK is not a verdict on the data. Rollback restores the database only when pending migrations were applied, and a failed restore is collected as a rollback failure — in which case the run ends as recovery_required rather than ROLLED_BACK.

The health gate reads /api/v1/status, which answers whenever the process is up; it proves the service started, not that every feature is enabled. Confirm the version actually serving, and whether the runtime suspended itself, at the administrator status endpoint:

Terminal window
Invoke-RestMethod http://127.0.0.1:3000/api/v1/admin/system/status

The response carries version, buildDate, schemaVersion and the current suspension state; the same values are shown in Administration → System status. Keep the terminal output, the state file and the dump path in every case.

Windows installations add three service operations that have no Linux counterpart, because the service is created and repaired by the same utility.

CommandWhat it doesWhat it never does
bootstrap-service --install-root <path> [--service MAIA] [--setup]Creates and starts an NSSM service for an installation that was deployed with --no-serviceReplace an existing service
repair-service --install-root <path> [--service MAIA] [--confirm]Reconciles Application, AppDirectory and the stdout/stderr log files with the managed layout; without --confirm it only prints the planModify unmanaged NSSM settings such as the account or the recovery policy
doctor [--install-root <path>] [--service MAIA] [--json]Read-only report of layout, service state, database and healthChange anything
Terminal window
.\MAIA-MAINTENANCE.exe doctor --install-root C:\MAIA --service MAIA
.\MAIA-MAINTENANCE.exe repair-service --install-root C:\MAIA --service MAIA --confirm

Two details decide whether a Windows update can proceed:

  • The service name must match. --service MAIA is the default the installer creates; a renamed service has to be named in every command, or the preflight blocks.
  • NSSM must be resolvable. The package bundles nssm.exe; an existing NSSM somewhere else is named with --nssm <path>. --service-driver nssm forces NSSM handling, native forces a sc.exe-registered service, and none skips service control entirely.

The Windows build ships in two variants: the standard mwtsolutions-maia-win.exe and MAIA-MAINTENANCE.exe, and the -baseline pair for CPUs without AVX2. Use the pair that matches the binary already serving; a baseline update over a standard installation is a downgrade of instruction-set assumptions, not a fresh install.

It runs when activation or the health gate fails:

  1. Restore the database — only if pending migrations were applied.
  2. Move previous back to current.
  3. Restore the service launch settings.
  4. Restart the prior service.
  5. Write the failure to the state file.

Without pending migrations there is no dump, and previous alone is enough.

After a failed attempt:

Terminal window
.\MAIA-MAINTENANCE.exe recover --install-root C:\MAIA --service MAIA
.\MAIA-MAINTENANCE.exe recover --install-root C:\MAIA --service MAIA --restore-database

recover restores the journaled database, the payload and the service configuration. Do not repeat --confirm on a half-switched root: it produces a worse state than a recover.

repair — also reachable as db-repair — rebuilds a candidate database from the canonical DDL, copies data on a best-effort basis, validates the candidate, and only then renames the production database to a timestamped archive. The archive is kept, not dropped — but it is a rename of the live database, so the data visible to the application is the rebuilt candidate. It requires --confirm-repair and a persistent --backup-dir, plus a DBA decision that the database is damaged or not migratable; it is not a normal upgrade step.

Rules that keep an installation recoverable

Section titled “Rules that keep an installation recoverable”
  • Migrations are forward-only. Editing a released .sql file produces Migration ledger mismatch; the fix is a new file, not an edit.
  • ddl.sql must equal src/db/unified_schema.sql. A divergence blocks the build, by design.
  • Keep previous and the dump until the release is accepted.
  • Never replace a live binary or MAIA-WEBUI/ with a loose copy — on Windows the service holds the .exe open, so a manual copy fails halfway instead of cleanly.
  • Signature files travel with the package — release-manifest.json and .sig are part of it.
SymptomMeaning
UPDATE BLOCKED before any changeA prerequisite failed; read the reason, fix it, re-run the preflight
Migration ledger mismatchA released migration was modified
Health gate fails after switchRollback ran; service is on previous
--pg-dump missing and not on PATHBlocked, because a verified backup cannot be produced
UPDATE BLOCKED: MAIA backend is still running under --no-serviceThe health endpoint answered, so the runtime is alive; stop it before a confirmed run
MAIA_MAINTENANCE_HEALTH_URL must be an HTTP(S) loopback URLThe health override is not a local URL without credentials
Repeated failure on the same rootUse recover, then investigate; do not stack --confirm attempts

Installation · Windows All-in-One installer · Backup and restore · Diagnostics · Troubleshooting: connections