Skip to content

Sovereign OS Roadmap

Status Legend

  • ✅ Complete — implemented and qualified on supported hardware
  • 🟡 In progress — implementation or hardware qualification is active
  • ⚪ Planned — accepted direction, not yet started
  • ⏳ Pending decision — research or an RFC must close the design boundary

Current Position

✅ Phase 01 — Flashable Raspberry Pi Image POC

The Raspberry Pi 5 image build, flash, first-boot, Pi-hole, persistent DATA partition, local routing, first-login, and Sovereign Console health experience have been exercised on physical hardware.

🟡 Milestone 01.1 — Appliance Update Foundation

The signed appliance updater can inspect, prepare, back up, stage, activate, health-check, commit, recover, and roll back versioned releases while preserving the dedicated DATA partition. An initial signed update transaction passed Raspberry Pi qualification.

The first fully versioned appliance-release qualification, from preview.9 to preview.10, exposed service-readiness and systemd dependency races. Automatic rollback worked and restored preview.9. The fixes were qualified on Raspberry Pi 5 hardware in a clean preview.11 base to preview.12 update campaign: an interrupted-at-validating recovery, a forced target-health rollback, and a successful activation all held with reboot persistence and no regression to Console, DNS, Pi-hole, Nginx, SSH, credentials, or the dedicated DATA partition. See the preview.12 appliance update qualification report.

Persistent-data restore, bounded retention (prune), and signed trust rotation (rotate-trust) are all implemented and hardware-qualified on Raspberry Pi 5, most recently against a real 0.1.0-preview.13 base image built and flashed with all three shipped in for the first time — see the preview.14 appliance update qualification report and the prune and trust rotation hardware qualification report. Production signing-key custody is decided (ADR-0006), and the production key (sovereign-production-1) is now generated, provisioned into the image-builder trust store, and proven end-to-end: v0.1.0-preview.17 is a real production-signed release that has been built, published, discovered, installed, and restored from on Raspberry Pi 5 hardware — see the first production-signed release, install, and restore qualification reports. prune and rotate-trust have not yet been exercised as part of a real signed-release install cycle.

Unattended automatic installation remains disabled until the manual, health-gated update path and its operational controls are qualified.

Milestone Sequence

1. Complete Appliance Update Qualification

Status: ✅ Complete

User outcome: Install a compatible Sovereign appliance release without reflashing or losing persistent data.

Qualification pair:

  • preview.11: clean flashable base containing the systemd and readiness fixes;
  • preview.12: signed, versioned installed-device update built from the same source revision.

The physical qualification on Raspberry Pi 5 proved:

  • update compatibility and signature verification;
  • staging without changing the active release;
  • interruption recovery (interrupted at validating, automatic boot-time restore of preview.11);
  • forced health-check failure and automatic rollback;
  • successful activation and commit;
  • reboot persistence;
  • preservation of Pi-hole configuration, credentials, update state, and the dedicated DATA mount; and
  • no regression to Console, DNS, Pi-hole, Nginx, or SSH.

See the preview.12 appliance update qualification report for full evidence.

2. Production Update Operations

Status: 🟡 In progress

Depends on: Completed preview.11 to preview.12 qualification

User outcome: A supportable update mechanism with trustworthy release and recovery operations.

Planned work:

  • automate persistent-data restore verification — sovereign-update restore is implemented and hardware-qualified against real Pi-hole state on Raspberry Pi 5, including a forced-health-failure rollback path, twice now: once manually deployed, and again on a real preview.13 base image that shipped it natively (see BACKUP_AND_JOURNAL.md and the restore and preview.14 qualification reports); it still has not shipped through a release used by anyone beyond qualification, and is not yet wired into automatic update rollback for future data migrations;
  • define bounded retention and cleanup for old releases, backups, journals, and failed transactions — sovereign-update prune [--dry-run] is implemented and hardware-qualified on Raspberry Pi 5 against real backups, releases, and transaction journals, including confirming the live device stays healthy through an aggressive real deletion pass (see BACKUP_AND_JOURNAL.md and the prune and trust rotation qualification report). Now wired into a daily sovereign-update-prune.timer (jittered, catches up on boot if a run was missed), hardware-verified running under its own hardened sandbox on Raspberry Pi 5; not yet shipped through a release beyond qualification, and an actual unattended timer-elapsed run has not been separately observed;
  • establish production signing-key custody, rotation, and revocation — decided in ADR-0006 (password-manager-held key, hardware key as a future upgrade). Routine rotation/revocation is implemented as sovereign-update rotate-trust (signed, atomic, refuses any change that would leave a channel with no trusted key — see update/README.md's "Trust Rotation v1" section) and hardware-qualified on Raspberry Pi 5, including the realistic single-key rotation handoff, immediate enforcement of revocation, and the lockout protection (see the prune and trust rotation qualification report). The production key (sovereign-production-1, Ed25519, scoped to both preview and stable) has now been generated under that custody decision and its public half is baked into the image-builder overlay's trust store, so future base images trust it out of the box; the private half lives only as an encrypted secret in the maintainer's password manager. v0.1.0-preview.17 is the first release signed with it, published, discovered, and — as of a full prepare/backup/stage/ activate run on the same Raspberry Pi 5 — genuinely installed: the device now runs 0.1.0-preview.17, update_state: committed, confirmed across a cold reboot. See the discovery and install qualification reports. That install campaign also found and fixed a real regression: sovereign-proof.service failing on any boot after prune removes the base image's own (now-inactive) release directory — proof-init now only performs that check during first-boot bootstrap. restore has since also been qualified against the real pre-activation backup that install created: correctly rejected a version-mismatched restore by default, then recovered an injected canary correctly under --force with no regression — see the production-signed restore qualification report. prune/rotate-trust still haven't been exercised as part of an actual signed-release install cycle — doing so meaningfully needs either a second real release or a genuine key rotation, not a manufactured scenario. Getting a rotation manifest onto already-flashed devices without an operator manually running the command still depends on the Update Discovery work in item 3 below;
  • approve the update RFC and production manifest policy;
  • publish release compatibility, rollback limitations, and recovery guidance — published as docs/operations/update-recovery-and-compatibility.md, written for the device operator rather than a contributor; and
  • qualify every supported source-to-target update path on real hardware. A 0.1.0-preview.170.1.0-preview.18 attempt surfaced a real structural gap: the installed updater's appliance file allowlist was fixed at flash time and couldn't learn about a new file added by the release introducing it. Fixed and hardware-qualified the same day — the validator now rejects only missing required files, not unrecognized ones, and classifies appliance scripts by shebang instead of a hardcoded name set; the exact real stuck transaction was recovered through to committed on real hardware, confirmed persistent across a reboot — see the finding and its fix qualification report. This does not touch the larger, still-unresolved question of delivering new systemd units/base-image content via update at all (see item 6 below) — only the narrower file-allowlist symptom.

3. Update Discovery and Console Controls

Status: 🟡 In progress

Depends on: Production Update Operations for the Console-facing and installation-triggering bullets below; the device-side check-and-notify bullet was deliberately scoped in RFC-0015 to not depend on it (no Console change, no production key) and has already started.

User outcome: Learn about and install x+1 from Sovereign Console without using the command line or reflashing.

Planned work:

  • publish signed update-channel metadata over HTTPS, and periodically check for compatible updates without sending household data — accepted in RFC-0015 and implemented as sovereign-update check, reusing the existing signed-manifest verification unchanged, with no new trust logic, no Console change, and no production key required. Runs daily via sovereign-update-check.timer, hardware-verified on Raspberry Pi 5 against the real live GitHub API, including the positive "update found" path against a genuinely published (non-draft) release — see update/README.md's "Update Discovery v1" section and the positive-path qualification report. That campaign also surfaced a real gap, now fixed: build-image.yml's release-publish step never uploaded the update-candidate manifest/bundle at all, and its filename collided with the image's own provenance file (now image-manifest.json). The workflow now conditionally uploads the unsigned update-candidate assets when build_update_candidate is selected; an operator still has to sign and upload the .sig offline before a release becomes discoverable;
  • Console authentication — the prerequisite ADR-0005 itself named before any mutating Console action can exist. Decided and implemented in ADR-0007: a separate Console-specific credential (sovereign-console-password), a loopback-only, systemd-hardened login backend (sovereign-console-auth, /api/v1/auth/*), session cookies with CSRF protection, and per-source rate limiting without lockout, with a sign-in UI wired into Console's topbar. Unit-tested (tests/test_console_auth.py) and hardware-qualified on Raspberry Pi 5 — see the console authentication hardware qualification report. A real signed-release install attempt (v0.1.0-preview.18) surfaced a structural finding bigger than Console auth itself — see the finding — since fixed: .18 is genuinely installed via a real update on real hardware, console-auth's binary included. The base-image content it also needs (systemd unit, sysusers.d group, directory bootstrap) was then deployed manually and permanently to the qualification device — real, accepted drift against what any future image build produces until the next reflash, not something an update can deliver (tracked at item 6 below). Console authentication is now genuinely live and working on real hardware;
  • the first Console-triggered privileged action — decided and implemented in ADR-0008: a file-existence trigger picked up by a systemd path-activated, root-owned oneshot runner, scoped to exactly one action, sovereign-update check. Hardware-qualified on Raspberry Pi 5 — the full chain (auth/CSRF gating, the trigger actually firing, a real check running as root, the result surfacing back to Console, cooldown enforcement) verified correctly, after finding and fixing two real defects (a missing ReadWritePaths= grant, and a static-group name that collided with an unrelated service's own DynamicUser identity) — see the qualification report. prepare/backup/stage/activate (an actual install trigger) are explicitly out of scope for this pass — deliberately smaller blast radius first;
  • show version, channel, release notes, download size, reboot requirements, and rollback limitations in Console;
  • provide user-triggered download and installation;
  • report download, verification, staging, activation, validation, rollback, and completion states; and
  • retain a CLI recovery path independent of Console.

The initial policy is notify and require approval. Automatic download and maintenance-window installation follow only after repeated field qualification. Every automatic policy retains signature verification, health-gated activation, and automatic rollback.

4. Local Conversation and Capabilities

Status: ⚪ Planned; research and RFC work may proceed in parallel

Depends on: Stable appliance update boundary

User outcome: Ask Sovereign local questions, inspect system and Pi-hole status, and explicitly use privacy-transparent, self-hosted web-search tooling.

Milestone 01.2 will deliver:

  • a Sovereign-owned conversation experience;
  • provider-neutral local inference and model-management contracts;
  • a Raspberry Pi 5 benchmark of llama.cpp and Ollama;
  • a typed capability registry and deterministic executor;
  • system.health and read-only Pi-hole capabilities;
  • opt-in web.search through a locally operated SearXNG instance;
  • restricted web.fetch, citations, privacy indicators, and audit events; and
  • real-hardware qualification within DNS-latency, memory, power, and thermal budgets.

5. Home Automation Integration

Status: ⚪ Planned

Depends on: Qualified capability executor

User outcome: Ask about and safely control allowlisted home entities through the same Sovereign conversation boundary.

The first slice is read-only Home Assistant entity discovery, state, and history. Later slices may propose allowlisted actions, but deterministic policy outside the model must authorize them and require confirmation according to risk. The model never receives unrestricted Home Assistant, shell, Docker, or network access.

6. Full Base-OS Updates

Status: ⏳ Architecture decision pending

Depends on: Stable appliance updater and persistent partition contract

User outcome: Update Debian, kernel, firmware, Docker, and early system services without reflashing.

The current updater covers versioned Sovereign appliance releases; it does not make base-OS package transactions atomic. The long-term milestone must select and qualify an A/B root-filesystem or equivalent immutable deployment design with:

  • persistent DATA independent of either system slot;
  • atomic boot-slot selection;
  • boot and health confirmation;
  • automatic fallback to the previous system;
  • signed system artifacts; and
  • an external recovery-image path.

This milestone closes the remaining “flash once” gap.

Progress Summary

  • ✅ Concept paper and master plan
  • ✅ Phase 01 appliance architecture decision
  • rpi-image-gen assessment, proof build, and automated ARM64 image pipeline
  • ✅ Flashable Raspberry Pi 5 image exercised on hardware
  • ✅ Docker-based Pi-hole, /dns/* routing, and persistent DATA
  • ✅ First-login credential-change and optional SSH-key flow
  • ✅ Sovereign Console read-only health page qualified on Raspberry Pi 5
  • ✅ Signed update transaction, interruption recovery, rollback, and persistence demonstrated on Raspberry Pi 5
  • ✅ Fully versioned appliance-release qualification (preview.11 to preview.12), including readiness hardening
  • 🟡 Persistent restore automation, retention, and production signing operations
  • 🟡 Update discovery and Sovereign Console update controls
  • ⏳ Local inference benchmark and conversation/capability RFCs
  • ⚪ SearXNG-backed web-search capability
  • ⚪ Home Assistant capability integration
  • ⏳ A/B or equivalent full base-OS update architecture

Phases

Project Documentation

Open source under AGPL-3.0. Each Sovereign instance is independently operated.