Peios Learn
Products
PePeios pkpekit PvProvium UDUniversal Directory TrTrail Ckclackatoo PrProject WiWispist
Using Peios Security Basics Technical Documentation Source
Using Peios Security Basics Technical Documentation Source
Peios

Editions and upgrades

Single-page view · as markdown

Editions

Peios / Peiso / Editions and upgrades

Peios has no channels and no release cadence. It is a rolling release with a full archive: every version of every package ever published stays installable. What it has instead of a channel is an edition — a package that says what a Peios is.

The edition package #

dev.peios.peios-experimental is the edition today. It retains peios-experimental as a compatibility capability for image composition and as the bounded name of pre-qualification installations. It is an ordinary peipkg package with an unusual job:

  • Its version is the OS version. dev.peios.peios-experimental 2026.8-12 is Peios 2026.8. The package writes /usr/lib/os-release (VERSION_ID="2026.8", VARIANT_ID=experimental, PRETTY_NAME="Peios 2026.8 Experimental") and the /usr/etc/os-release compatibility symlink, so a system's identity and its release are one fact, tracked in the package database.
  • Its dependencies are the base system. Kernel, modules and firmware; the initramfs — prelude, its hooks, the module subset and its own base tree, each placed IN initramfs explicitly; the service manager, registry, identity and networking daemons; the installer. Installing the package into an empty root yields a bootable Peios.
  • It provides peios-release. Depend on that virtual name to mean "some Peios"; depend on the edition to mean that edition.
  • It ships release.toml: what the release asks of a system beyond its packages, as data.
  • It declares an alternate upgrade path. peipkg refuses to install or upgrade it by name, holds it back from an upgrade of everything, and prints the message it carries: To upgrade Peios use the upgrade-peios command. The reasons are below.

"Experimental" is a name, not a channel. It marks that Peios is not yet production-ready and says nothing about cadence. When enough exists for the split to make sense it is replaced by peios-pro, peios-minimal, peios-desktop and so on — each its own package, each providing peios-release, each shipping its own os-release.

What the edition deliberately does not contain #

Three things a live medium needs are absent from the edition, because they are properties of the medium:

  • live-boot and disk-boot. Which boot packages a system carries depends on what it boots from. The installer swaps one for the other on the target; an edition that named either would be installable on only one kind of medium.
  • peios-dwe. The Developer Workstation Environment makes a machine ownable. It is added by peiso for a development medium and could never be a thing that arrives by installing a package.
  • Anything the installer is not. peios-install is in the edition: an installed system can install another.

Pinning #

Experimental's dependencies are >= floors — a floor lets a package move without republishing the edition on every change, which is right for a pre-alpha. A production edition pins exact versions, and then something useful follows: peipkg upgrade cannot move a pinned dependency past what the edition allows, so a real release upgrades as a unit, through upgrade-peios, never piecemeal.

Why the package manager will not move it #

Installing a package on Peios cannot change system policy. A package delivers files; which services run and which policies apply is decided by registry seeds that a package can only offer. That is the deliberate weakness that lets packages be installed freely.

Moving from one release to the next is more than a package upgrade: the new release's seeds have to be reconciled, and that is precisely the thing peipkg must not do. So the edition declares, in its manifest, alternate_upgrade = { message = "To upgrade Peios use the upgrade-peios command." } (PSPU §5.18). The declaration grants nothing — a package cannot name a command for the consumer to run, let alone run one. Its whole effect is that peipkg stops and shows the message, with a warning that whatever the message names sits outside the package manager's protections. The person runs upgrade-peios, which drives peipkg with --bypass-alternate-upgrade and then does the reconciling itself.

Where an edition lives #

The recipe is pkgs/dev.peios.peios-experimental/ in the Peios tree: a pekit.toml whose build writes os-release and release.toml, and a package.pekit.toml with the dependency table. Changing what Peios contains is a change there, followed by a republish. peiso and its spec do not change.

release.toml

Peios / Peiso / Editions and upgrades

An edition package ships /usr/share/peios/release.toml. It states what the release asks of a system beyond its packages. peipkg never reads it; two tools do:

  • peiso, when composing an image, to stage the seeds into the medium.
  • upgrade-peios, to stage and apply the installed release's autoapply seeds, including when an ordinary CLI package request is a no-op or declined. Read the upgrade warning and preview procedure before invoking it.

Both act as the operator, deliberately; the package manager acts as neither.

Contents #

This example shows the three queues, including the GXWI desktop seeds listed in the Experimental quick start. It is not an exhaustive release manifest: inspect the selected edition's /usr/share/peios/release.toml for its complete lists.

# Example registry queues. Read by peiso and upgrade-peios.
[registry]
autoapply = [
  "port-reservations",
  "eudev-service",
  "authd-service",
  "authd-policy",
  "lpsd-service",
  "lpsd-authd-registration",
  "login-console",
  "eventd-config",
  "eventd-service",
  "netd-service",
  "netd-default-profile",
  "resolvd-service",
  "resolvd-port",
  "gxwid-service",
  "gxwi-config",
  "gxwi-network",
  "fenestra-config",
  "fenesh-config",
]

# The boot medium applies these and an installed machine does not.
live_autoapply = [
  "lpsd-first-account",
]

# Only an installed machine applies these.
install_autoapply = [
  "oobe-service",
]

Three lists, because a seed has a place #

A seed can belong to the medium, to the machine an installer writes, or to both. The distinction exists because an installer copies the shipped image verbatim: whatever is staged onto the medium arrives on the disk too, unless something takes it off again.

Two opposite cases make that matter, and before the split neither could be said:

  • lpsd-first-account provisions the development account whose password ships in the image and is therefore public. Right on a live medium; a hole on an installed machine — which used to get it, and then crash the provisioner against its own account on every subsequent boot.
  • oobe-service runs first-boot setup, which asks for a real account. Right on an installed machine; on the medium it would take the console away from the installer.
KeyStaged intoApplied by
autoapplylcl/policy/autoapply.d/every system, on first boot
live_autoapplylcl/policy/autoapply.live.d/the boot medium only
install_autoapplylcl/policy/autoapply.install.d/the installed machine only

Each names a master a package in the edition's closure ships at /usr/share/regim/<name>.reg; listing it is what opts it in. A reader treats a name nothing ships as an error, and a name in two lists as an error too — it would be staged and drained twice, and in every case it means the release said something it did not mean.

peinit's drain applies the first two, base before live, so a live seed can override a value the base one set: the medium is the special case, and the special case goes last. It never touches the third. The installer is what promotes autoapply.install.d/ into the target's autoapply.d/ and deletes autoapply.live.d/ — the act that turns a copy of a medium into a system.

Nothing else is defined yet. Unknown keys are rejected by both readers, so the file can grow without silently meaning nothing to an older tool.

What is not here #

  • dwed-service. The DWE seed is peiso's to add, for a development medium only; a release never applies it. peiso stages it into the live queue, on the same reasoning that puts the development account there: a machine installed from a DWE medium is a machine, and a vsock control channel into it is not something the operator asked for.
  • Anything a medium adds. live-boot and the medium repository are the image's, not the release's.
  • Seeds that were removed between releases. A seed present in 2026.8 and absent in 2026.9 is not un-applied by anything today; the registry keeps its history and that is where the record lives. This is the same limitation an edition has with packages it stops depending on, and it is deferred to the same future mechanism.

Why a file, and not a package field #

peipkg's manifest is the wrong place for this, on purpose. A field the package manager acted on — "apply these seeds when I am installed" — would let any package change system policy by being installed, which is the one thing Peios packages must not be able to do. As a file that only deliberate tools read, the list is inert until someone who has chosen to build an image or upgrade a system acts on it.

Upgrading Peios

Peios / Peiso / Editions and upgrades

Use upgrade-peios to move the edition package and reconcile the release's registry seeds. First inspect the installed release and preview the package plan:

upgrade-peios --status
upgrade-peios --check

--check does not apply the package plan or stage or apply registry seeds. Planning can still refresh repository metadata for peipkg's trust-freshness checks. It is a preview against the inputs available then, not a reserved plan for a later invocation.

Warning

Plain upgrade-peios can reapply policy even when no package changes. In the source versions described below, a package plan with nothing to do, or a package prompt you decline, returns success to the updater. It then stages the installed release's seeds and, on the live root without --on-reboot, applies the seed queue. Do not run the plain command just to look for updates, or rely on declining its package prompt to leave registry policy alone.

When you intend both the package update and seed reconciliation, run:

upgrade-peios

Re-running can finish seed work left by an interruption, but it also copies the installed release's seed masters into the queue again. Review the release's policy changes and preserve important local configuration before reapplying them. A failed package transaction needs the package recovery procedure, not an assumption that every interrupted step completed.

What happens #

  1. Find the edition. upgrade-peios reads ID and VARIANT_ID from /usr/lib/os-release — the file the edition package itself wrote — and derives the edition package's name from them: VARIANT_ID=experimental is dev.peios.peios-experimental. A system whose ID is not peios, or that has no variant, is refused (exit 2).
  2. Move the edition package. It runs peipkg upgrade dev.peios.peios-experimental --bypass-alternate-upgrade, passing --yes and --allow-stale through when given. The upgrade pulls the release closure with it. A peipkg failure is exit 3, and the updater stops before its seed steps. In ordinary CLI mode, peipkg exit 0 also includes a no-op or a declined prompt; those outcomes still reach the next step.
  3. Stage the installed release's seeds. The installed release.toml is read, whether or not the package version changed; each seed it names is copied from /usr/share/regim/ into /lcl/policy/autoapply.d/, and the drain script is placed in /lcl/policy/autorun.d/ if it is missing. A seed the release names that nothing ships is exit 4.
  4. Apply the queue. Unless staging for boot, reg apply --dir /lcl/policy/autoapply.d --once-delete --yes applies the queued seeds and removes successfully applied files. This command is run when the release names seeds and targets the whole directory, including other seeds already queued there. Registry policy and service definitions can change; verify their intended effects separately. Failure is exit 5, and is not a rollback of package changes or already-applied seeds.

upgrade-peios never elevates. peipkg and reg run with the caller's token, exactly as they would if you typed the two commands yourself; KACS decides what each may do.

An installation whose upgrade-peios itself predates the qualified package name is covered too. Its old concrete request for peios-experimental selects the final 2026.8-10 legacy migration release. That dependency-only release requires dev.peios.peios-experimental; the successor's bounded replaces edge removes the legacy package in the same transaction. The migration release therefore never enters the installed result. The successor also conflicts with the legacy name, so trying to install the trampoline into an empty system fails rather than leaving two edition identities behind.

Options #

--on-rebootStop after staging. This still writes the seed queue, including after a plain-CLI no-op or declined package prompt. The seeds apply on the next boot, when peinit runs the drain script before planning its services. Use this when a seed changes something you would rather not change under a running session — the console login, say.
--seeds-onlySkip the package upgrade and only reconcile the installed release's seeds. This is the re-run: after an interrupted upgrade, or to re-apply a release's policy.
--yes, -yPass --yes to peipkg.
--allow-stalePass --allow-stale to peipkg: carry on with a repository's out-of-date information when refreshing it brought nothing newer.
--checkPreview peipkg's package plan with --dry-run; do not apply that plan or stage or apply seeds. Trust-freshness checks can still refresh repository metadata.
--statusShow the installed release, the edition package's version, the seeds waiting for the next boot, and whether you may upgrade.
--root DIROperate on the Peios rooted at DIR rather than /. A non-live root implies --on-reboot: seeds are still staged there, but reg is not run against the live registry. peipkg is run with --root DIR.

To do it on the desktop, use Upgrade Peios. It uses driven mode: a cancelled result stops before seed staging and application. This cancellation handling differs from the ordinary CLI's exit-status check. A driven done result with no package operations is not cancelled; without --check, it can still reach seed reconciliation.

Check the outcome #

Separate the package result, the seed result, and the running system:

  1. Read the package result and warnings. peipkg exit 0 alone does not establish that an upgrade was performed or approved.
  2. Run upgrade-peios --status again, using the same --root DIR for an alternate root. Compare the installed edition version and queued seeds. An unreadable queue is unknown, not empty. After --on-reboot, staged seeds are expected to remain until boot applies them.
  3. If staging or application failed, read the failed step before retrying. Earlier seeds may already be staged or applied. --seeds-only stages the installed release's complete autoapply list again; it is not a read-only check or a reversal of the failed attempt.
  4. Verify affected registry policy and the software that uses it. An empty queue does not by itself prove every intended service or policy is working. Package undo does not restore registry state or undo a feature's setup; see recovery limits.

--status reads installed release/package metadata and the queue. It does not identify the currently running kernel or mapped service binaries. This updater invokes peipkg and reg; that path does not itself run a reboot or boot-image regeneration command. Do not use its successful exit or status as proof that all installed code is active or that every kernel update's boot artifacts are ready. Upgrading from the medium is a separate path with explicit boot-file regeneration.

Check what an update has activated #

Use these inspection steps after reviewing the package and seed results above. They do not regenerate boot files, start services or restart the machine. If a step cannot be verified, record boot activation not yet verified rather than treating the update as ready to boot.

Compare installed and running code #

For a kernel update on the live system, record:

uname -r
peipkg info dev.peios.kernel
peipkg files dev.peios.kernel

uname -r identifies the running kernel release. Compare it with the intended release in the installed kernel's payload paths, not directly with the edition or package version: those are different identifiers. A difference before restart is not proof that a restart will select the new kernel. For alternate roots, select the intended package root separately; uname still describes the running system.

Service status gives state, job, PID and start information, not an executing binary's build identity. svctl --version is the client version. Use the affected service's own reload/restart requirements and functional checks; package installation or a registry-definition reload does not prove it has adopted new code.

Inspect Dynamic Boot's actual state #

The located live regeneration mechanism is the optional Dynamic Boot feature, whose scripts define mkirf-watch and mkuki-watch. Package delivery, feature setup, enablement and running services are separate states:

feat info dynamic-boot
svctl status mkirf-watch
svctl status mkuki-watch
svctl definition show mkirf-watch
svctl definition show mkuki-watch

The reviewed feature initially creates disabled services. Enabling it after boot clears that flag but does not retroactively start them; disabling it does not stop an already-running watcher. Image setup before boot-time service enumeration can differ. Check the actual services rather than inferring their state from the feature record. This section supplies no automatic start or restart sequence.

In the packaged definitions, mkirf-watch writes /system/boot/initramfs.cpio.zst, and mkuki-watch writes /boot/efi/EFI/BOOT/BOOTX64.EFI. Verify the definitions on your machine. The UKI launcher chooses its command-line input at startup: a nonempty /lcl/etc/boot/cmdline, otherwise /usr/share/live-boot/cmdline. Creating the preferred file later does not prove an existing watcher switched to it.

Verify the destination and rebuild evidence #

Before relying on watcher output, use storage inspection to identify the intended EFI System Partition and the filesystem at the output path. Plain mount lists mounts visible in the caller's namespace; that is not proof of firmware selection or another namespace's view.

Warning

mkuki can create missing output directories without checking that they are on the intended ESP. A wrote message can therefore describe an ordinary directory, not the boot partition. The reviewed feature scripts do not supply a complete ESP-mount arrangement. If the mapping is absent or uncertain, stop the boot-readiness claim; do not choose a device or create a mount recipe by guesswork.

In Services Manager, inspect Logs… for each watcher over the update's job/time interval. Both can report rebuild failed and remain running; an Active/Alive state or watching message is not build success. mkuki also rejects zero or multiple regular vmlinuz-* candidates rather than selecting the newest one.

Look for successful cpio replacement and a subsequent successful UKI rebuild using the final settled inputs, retaining all rebuild/watch errors. A wrote message follows output replacement, but the watchers run independently of the package transaction: it is not an all-input generation or bootability attestation. Intermediate builds can observe different update stages. Missing logs or timestamps alone cannot establish success; log visibility and delivery limits still apply.

Check after a separately planned restart #

Only follow the machine's supported restart procedure once its prerequisites and recovery access are established. After it actually boots, run uname -r again and compare the intended release. Check queued-seed state, affected service jobs/status and their functional behavior separately. An accepted restart request, installed edition name or old successful build message does not replace these observations.

The installer-medium upgrade is a separate path that mounts its selected ESP and explicitly rebuilds boot files. It is not evidence that the live watcher destination is configured, nor a harmless generic repair.

Activation evidence and scope #

This checklist follows pinned static source, not a deployed-system test:

  • Dynamic Boot setup, enable, disable, and launcher paths.
  • mkirf failure handling and mkuki watch/build behavior.
  • Kernel payload naming and running-kernel readback.
  • Installer boot-file generation.

Check applicability to your image. These sources establish separate stages, not a complete live ESP setup, combined artifact verifier or successful boot.

For a program #

upgrade-peios --status --json answers with one object:

MemberIs
editionThe edition package's name.
name, version_id, variantPRETTY_NAME, VERSION_ID and VARIANT from os-release.
versionThe edition package's installed version, or null where peipkg's records can't be read.
queued_seedsThe seeds waiting in /lcl/policy/autoapply.d/ for the next boot, by name, or null where the queue can't be read.
may_upgradeWhether you may upgrade: asked by opening peipkg's lock and database for writing and checking the seed queue is writable. Nothing is written.

upgrade-peios --driven upgrades, or with --check looks, and reports it as JSON Lines events on standard output. Its first part is peipkg's driven mode: peipkg is run with upgrade-peios's standard input, so the program answers peipkg's questions as it would answer peipkg's own, and every event peipkg writes is passed on except its terminal one. Then upgrade-peios adds:

EventMembersMeans
progressphase, step, stepsphase is release-stage (the seeds are copied into the queue) or release-apply (they are applied).
messagetextWhat upgrade-peios is doing, or a line reg wrote.
donesummary, edition, seeds_queuedFinished; seeds_queued is true when the seeds were left for the next boot.
cancelledreasonpeipkg's plan wasn't approved; the updater stops before staging or applying seeds.
errorcode, messageFailed. The code is peipkg's own for its part (stale, busy, denied, unresolvable, untrusted, failed…), or usage, no-release, seeds or apply.

Exactly one done, cancelled or error ends the run. --yes is refused with --driven. A program that goes away mid-upgrade doesn't stop it.

From the medium #

A machine with no reachable repository is upgraded from an image instead: boot it from the new medium with its disk attached and choose Upgrade an installation in the installer. That runs the same procedure against the mounted disk — the edition with the bypass, --seeds-only for the seeds, then everything else the medium carries — and rewrites the boot files. The medium's repository index is fixed at manufacture, so the installer always passes peipkg --allow-stale, which this command does only when asked.

Why not peipkg upgrade #

peipkg upgrade upgrades every package it can and holds the edition back, printing the edition's message:

The package "dev.peios.peios-experimental" has an alternate upgrade path.

To upgrade Peios use the `upgrade-peios` command.

Warning: Alternate upgrade paths may bypass normal peipkg protections; ensure you fully trust the authors of the package before running.
held back: dev.peios.peios-experimental 2026.8-12 -> 2026.9-1

peipkg upgrade dev.peios.peios-experimental refuses outright with the same text. peipkg upgrade peios-experimental cannot name the installed qualified package at all: named upgrades intentionally do not resolve through provides. This is not peipkg being unable to move the edition; it is peipkg declining to do only half the job. Moving a release also means reconciling its seeds, and applying registry seeds is exactly what the package manager must never do on a package's behalf. The refusal keeps that line where it is, and the bypass used by upgrade-peios is the deliberate act that crosses it.

Once editions pin their dependencies exactly, this becomes the only way a release moves: peipkg upgrade cannot carry any pinned package past what the installed edition allows, so the system upgrades as a unit or not at all.

What it does not do #

  • It does not upgrade packages outside the edition's closure that the edition merely floors. With >= floors, peipkg upgrade afterwards brings the rest current; with pins there is no "rest".
  • It does not un-apply seeds the new release dropped. See release.toml.
  • It does not reboot or verify runtime activation. Check the running system separately from the installed package version.

Source and release scope #

The CLI/driven distinction above follows peiosutils 3344d469's upgrade path, its seed-copying step, and peipkg 8b588ae8's plan/approval return path. Peipkg performs trust-freshness checks before its dry-run boundary. The status implementation establishes the limits of the inspection command. These are source-backed behaviours, not a live cancellation/upgrade test or proof that a particular released image includes these revisions. Check the tool versions supplied by the image you operate.

Upgrade Peios

Peios / Peiso / Editions and upgrades

Upgrade Peios is the desktop's window on upgrade-peios. Open it from the launcher (type upgrade). It has no authority of its own: it runs upgrade-peios --driven as you, with the same package and seed operations. Driven mode handles an explicit cancellation separately: a cancelled result stops before release seeds are staged or applied. Do not apply the ordinary CLI's declined-prompt warning to that driven cancellation result.

The release #

At the top is the release installed on this machine, as its name (Peios 2026.8 Experimental) and its edition package with that package's version. Beside it, once Upgrade Peios has looked: Up to Date, a newer release Available, or Not Checked when the look was refused.

Looking for a newer release #

Upgrade Peios looks as it opens, and again with Check Now or Check Again. A look refreshes the repositories this machine trusts, updating cached metadata, then previews the package plan without applying it or staging or applying release seeds.

It refreshes only repositories already trusted: a repository set up but never confirmed is confirmed in Package Manager, under Repositories, never as a side effect of looking.

When a newer release is offered, the page shows every change upgrading makes — the edition package and whatever of its release comes with it — with what it downloads and takes once installed.

Upgrading #

Apply Its Settings at the Next Restart chooses when the release's settings (its registry seeds: which services run, which policies apply) take effect. Off, as it starts, they are applied as soon as the release is installed. On, they wait for the next restart; use it when a setting would change something under the people signed in now.

Upgrade to … makes the upgrade. The changes it makes are the ones just shown; if they differ by the time it starts, because a repository changed in between, the new changes are shown and asked about again. Anything peipkg needs your specific approval for, such as a package moving back to an older version, is asked on its own, as in Package Manager.

The page then shows how far it has got: downloading and checking, putting the release in place, recording it, then gathering and applying the release's settings. Once the upgrade is approved it is made to the end even if you close the window, which stays, saying so, until it is done.

The upgrade doesn't restart the machine. Its displayed release and completed package/seed steps do not establish which kernel or service binaries are running. Follow the outcome checks, and follow the activation inspection checklist before relying on a kernel update.

When something stops it #

  • A repository's information is out of date, and refreshing it brought nothing newer. Continue Anyway carries on with what this machine already has, as --allow-stale does, and is recorded. Upgrade Peios remembers it until you close it.
  • A repository isn't trusted yet. Confirm it, or remove it, in Package Manager.
  • Another change is being made. Try Again once it has finished.
  • The release's settings couldn't all be applied. The release is installed; its settings wait for the next restart, which tries them again.

Settings waiting for the next restart #

When some of the release's settings are waiting for the next restart — left by an upgrade made that way, or by one that stopped part-way — the page says so, with Apply Now to apply them at once, as upgrade-peios --seeds-only does.

What you may do #

Whether you may upgrade is asked of the system, by upgrade-peios. As shipped, only Administrators may. Anyone else sees the release, with the reason said once, and nothing to press.

Software other than Peios itself is updated in Package Manager, which holds the edition back and points here.

The driven invocation is established by gxwi-upgrade-peios f40e8d8b. The release updater's source scope also applies; a source revision is not proof of the version in an installed image.

Peios Learn — documentation for the Peios project.

Built with Trail.