Windows Autonomous Appliance
A qualified Windows laptop is only the starting point. After installation, the School Server must behave like an appliance: it should recover after reboot, protect itself during power/disk incidents, maintain trust/time, prove backups are restorable, and produce machine-readable health without waiting for a technician.
The canonical implementation is shipped in mn-school-be/deploy/school-bundle. install.ps1 installs the normal Compose stack and then installs the Windows appliance control layer. Do not recreate these jobs manually with unrelated local scripts.
The current Windows appliance control plane registers thirteen Makronexus-* Scheduled Tasks and persists mutable commissioned state beneath C:\ProgramData\Makronexus\SchoolServer.
Persistent state and active release
Versioned release folders are disposable software. Commissioned identity/configuration is not.
The Windows preparation layer maintains:
C:\ProgramData\Makronexus\SchoolServer\
├── .env.school
├── active\ # junction to the active signed release bundle
├── backups\
└── runtime\
Each release-local runtime directory is linked to the persistent runtime. The release-local .env.school is linked to the canonical ProgramData environment so Compose service-level env_file: ./.env.school cannot drift away from the commissioned configuration.
Persistent state wins during install/update. A newly extracted release must not overwrite the existing SITE_ID, zero-touch enrollment identity, local CA, hold state, or durable appliance environment.
Thirteen autonomous Scheduled Tasks
All appliance tasks run elevated under the Windows SYSTEM service account. Recurring tasks use non-overlap settings so a slow run does not start a second copy of itself.
| Scheduled Task | Default trigger | Responsibility |
|---|---|---|
Makronexus-Container-Runtime | startup + logon | Start/reconcile Docker Desktop/Engine before the application stack. |
Makronexus-Boot-Reconcile | startup + logon | Reconcile Compose, wait for required containers, record boot health, capture diagnostics on failure. |
Makronexus-Watchdog | every 2 min | Recover Docker/WSL where possible, reconcile unhealthy/missing containers, rate-limit repair, capture repeated-failure diagnostics. |
Makronexus-Power-Guard | every 2 min | Use laptop battery as short-duration UPS and gracefully stop/shutdown at confirmed critical battery. |
Makronexus-Disk-Guard | every 10 min | Monitor disk headroom, rotate safe old artifacts, and stop write-facing services before the disk becomes unsafe. |
Makronexus-Nightly-Backup | daily 02:15 | Create a complete checksummed School Server backup with retention and optional external copy. |
Makronexus-Certificate-Maintenance | daily 03:15 | Maintain server self-resolution, renew local LAN TLS when expiry/hostname/IP changes require it, publish client trust material and reload nginx. |
Makronexus-mDNS-Responder | startup + logon + 5-min recovery | Advertise/respond for the canonical .local School Server hostname and HTTPS service on the active LAN interface. |
Makronexus-Time-Sync | daily 04:15 | Reconfigure/check Windows Time against the configured NTP source. |
Makronexus-Release-Integrity | daily 04:45 | Re-hash shipped bundle files against release-checksums.json. |
Makronexus-Weekly-Restore-Test | Sunday 05:15 | Restore the newest PostgreSQL dump into an isolated temporary DB and prove it is usable. |
Makronexus-Hardware-Health | daily 05:45 | Record memory/CPU, battery degradation, storage health and available reliability counters. |
Makronexus-Update-Availability | daily 06:15 | Check an explicitly configured HTTPS approved release manifest; report only, never activate. |
Confirm the installed task set:
Get-ScheduledTask -TaskName 'Makronexus-*' |
Sort-Object TaskName |
Select-Object TaskName, State
The watchdog also audits this task set and publishes runtime\task-status.json. Core recovery/safety tasks (container runtime, boot reconcile, watchdog, power guard and disk guard) are treated as critical controls. Maintenance/protection tasks remain visible as warnings when their scheduler state is unhealthy; their actual protection objectives are measured separately by backup, certificate, clock, hardware and other health checks.
Boot and Docker/WSL recovery
Container restart: unless-stopped handles many container-process crashes, but it cannot repair a Windows host where Docker Desktop or its WSL backend did not return after a reboot/power event.
The Windows control layer therefore separates runtime recovery from stack recovery:
The two-minute watchdog repeats runtime + stack checks during normal operation. Repair attempts are rate limited; repeated failures create diagnostics rather than an uncontrolled restart storm.
Persistent holds: fail closed instead of fighting incidents
The control layer uses runtime\hold-*.json to represent intentional stop conditions. Boot and watchdog jobs respect holds instead of continuously restarting services around an unsafe condition.
Current hold categories include:
disk-pressure— insufficient safe disk headroom;power— confirmed low-battery graceful shutdown;maintenance— supervised update/recovery in progress or failed closed.
Do not delete a hold just to make the UI come back. Resolve the underlying condition, then use the documented recovery path.
Disk guard
Default Windows thresholds are:
APPLIANCE_DISK_WARNING_GB=50
APPLIANCE_DISK_CRITICAL_GB=20
APPLIANCE_DISK_RECOVER_GB=30
At the warning threshold the appliance records attention. Below the critical threshold it creates a disk-pressure hold and stops backend/frontend/workers/nginx so PostgreSQL/MinIO are not driven into a completely full filesystem. Once free space reaches the recovery threshold and no other hold exists, normal reconciliation can resume.
The guard deliberately does not run automatic Docker image pruning. At an offline school, cached images may be the only rollback path.
Battery-backed graceful shutdown
The laptop battery is treated as short-duration power resilience, not as permission to run indefinitely without mains power.
Automatic shutdown requires:
- Windows positively reports AC power offline;
- charge is at/below
APPLIANCE_BATTERY_SHUTDOWN_PERCENT(default15); - two consecutive power-guard observations confirm the condition.
The second observation writes a power hold, gracefully stops the Compose stack, then requests Windows shutdown with a delay.
If Windows cannot determine AC state, the guard records a warning and deliberately does not shut down. Configure BIOS/UEFI automatic power-on after AC return where the laptop supports it; otherwise physical power-on is still required after a full protective shutdown.
Complete local backup and restore proof
Default Windows local backup directory:
C:\ProgramData\Makronexus\SchoolServer\backups
The nightly appliance backup is broader than a PostgreSQL dump. It quiesces application writers and captures:
- PostgreSQL custom-format dump;
- MinIO object data;
- persistent application key material;
.env.schooland release/image metadata;- runtime identity and
.env.localwhen present; - appliance local CA/server TLS material;
- backup metadata and SHA-256 checksums.
The weekly restore test validates checksums, restores the latest dump into a temporary database, requires a non-empty public schema, then removes the temporary database. A file existing on disk is not treated as proof of recoverability.
Local backup still shares the host failure domain. Configure APPLIANCE_BACKUP_EXTERNAL_DIR only to encrypted/protected USB/NAS storage and follow the governed DR policy in Backup, Restore, and Server Replacement.
Certificate, local name, mDNS and time maintenance
Windows certificate maintenance uses native Windows NIC/IP discovery plus OpenSSL. It renews the server certificate when it is missing/invalid, near expiry, the configured hostname/alias changes, or active IPv4 addresses change. The local CA remains stable so client trust survives ordinary server-certificate renewal.
The same maintenance script keeps a managed Windows hosts block for server self-resolution:
# BEGIN MAKRONEXUS SCHOOL SERVER LAN IDENTITY
127.0.0.1 school.makronexus.local school.makronexus.lan
# END MAKRONEXUS SCHOOL SERVER LAN IDENTITY
That loopback mapping is for the School Server itself. LAN clients use the School Server mDNS responder, school DNS/DHCP DNS, or another approved LAN name-resolution path. Makronexus-mDNS-Responder publishes runtime\mdns-responder-status.json with the active interface/IP and recent query/response evidence.
If the server itself cannot resolve school.makronexus.local while HTTPS succeeds with an explicit host/IP mapping, inspect the managed hosts block and Makronexus-Certificate-Maintenance. If other LAN devices cannot resolve the hostname, inspect the mDNS task/status and the LAN rather than treating the two failures as the same problem.
The time task keeps W32Time configured and attempts a resync using APPLIANCE_NTP_SERVER plus the configured fallback. Clock correctness matters because Cloud machine requests are replay protected.
Neither local self-resolution nor mDNS replaces governed school LAN addressing/DNS policy where centrally managed DNS is available.
Hardware degradation monitoring
Initial qualification answers “is this machine acceptable now?” Daily hardware health asks “is this appliance deteriorating?”
The hardware task writes runtime\hardware-status.json with available evidence for:
- memory pressure;
- CPU load/logical processors;
- battery charge and estimated health where design/full-charge capacity is exposed;
- physical disk health/operational state;
- available storage reliability counters such as temperature, wear and errors.
Clearly unhealthy/lost-communication storage is a failure. High wear/temperature, low battery health and incomplete telemetry are warnings requiring operator judgement.
Update discovery is autonomous; activation is not
By default:
APPLIANCE_UPDATE_MANIFEST_URL=
APPLIANCE_UPDATE_CHANNEL=stable
If an approved endpoint is configured, it must use HTTPS and return release-manifest JSON with at least releaseVersion. The appliance can report CURRENT, UPDATE_AVAILABLE, REMOTE_OLDER, CHANNEL_MISMATCH, or a safe failure/unknown state in runtime\update-availability.json.
The policy is intentionally report-only. A School Server does not download/apply a release merely because a newer manifest exists.
Use an approved maintenance event for activation. Prefer the supervised Windows path when you want a mandatory pre-update backup:
powershell -ExecutionPolicy Bypass -File .\supervised-update.ps1
Automatic rollback remains explicit opt-in because a database migration may make an older application binary unsafe against the upgraded schema.
Machine-readable operating state
Persistent runtime state includes, when applicable:
server-qualification.json
windows-state.json
active-release.json
boot-health.json
watchdog-health.json
backup-status.json
backup-verify.json
disk-status.json
power-status.json
certificate-status.json
mdns-responder-status.json
time-status.json
integrity-status.json
hardware-status.json
task-status.json
update-availability.json
container-health.json
update-status.json
last-appliance-error.json
support\diagnostic-*.txt
Core state/holds can be viewed with:
powershell -ExecutionPolicy Bypass -File .\windows-appliance.ps1 -Action Status
ERP School Server operations dashboard
Authenticated local/hybrid ERP users can open the tenant School Server resource at:
/{tenant}/operations/offline-sync/school-server
The page combines application and host posture in one control surface:
- PostgreSQL, Redis, object storage and container health;
- backup freshness, LAN certificate and clock integrity;
- Windows AC/battery status and graceful-shutdown posture;
- disk-guard free-space thresholds and protective writer hold;
- memory, CPU, battery degradation and physical-storage health/reliability counters;
- the thirteen autonomous Scheduled Tasks, including last/next run and last result;
- installed versus approved candidate release from update discovery;
- write authority, browser-local queue, Cloud queue, conflicts and replication state.
The browser consumes the authenticated local-only cloud-sync/appliances/platform/local/operations-health API. That surface is curated and no-store: it does not return machine credentials, update-manifest/download URLs, task command lines, environment paths, support-bundle paths, or raw release candidate metadata.
The operations dashboard is observation-only for Windows host controls. It cannot disable Scheduled Tasks, cancel a low-battery shutdown, prune storage, clear safety holds, or activate an update. Host recovery remains owned by the signed appliance scripts and governed maintenance procedures.
The existing pre-login /local/health endpoint remains intentionally summarized for commissioning/readiness and is not expanded with detailed host posture.
Windows commissioning acceptance
Do not hand over the server until all apply:
- Windows qualification is
PASSor reviewedWARN, neverREJECTED. - Windows software/Docker preflight passes.
-
install.ps1completed including persistent-state and autonomous-task setup. - all thirteen
Makronexus-*tasks exist. -
task-status.jsonreports all core recovery/safety tasks installed and enabled. - ProgramData persistent state and the
activerelease pointer exist. - no unexpected
hold-*.jsonexists. - initial hardware health has no
FAIL. - a manual complete backup succeeds.
- manual restore verification succeeds.
- a controlled Windows reboot returns the appliance healthy without manual Docker/Compose commands.
- trusted HTTPS works from another LAN laptop.
- the School Server operations dashboard shows current host telemetry rather than stale/missing snapshots.
- zero-touch enrollment, write authority, sync and WAN-offline acceptance are correct.
- the laptop remains dedicated, physically secured, normally on AC and preferably wired Ethernet.