Keeping a system current

For routine maintenance, refresh, review the upgrade plan, apply it, then check the outcome. First choose the intended root and preserve important local changes. upgrade can also update nested roots, so review the whole plan and check every participating root afterwards.

peipkg refresh
peipkg upgrade --dry-run
peipkg upgrade
peipkg history
peipkg verify

Read refresh failures before proceeding: a dry run and the final invocation can use different inputs if metadata or installed packages changed in between. After the change, review verification differences and configuration-file warnings, and check the affected software separately. A file check does not establish that a service or feature is working. For kernel and service updates, follow Check what an update has activated to distinguish installed payloads, boot artifacts and running code.

Your situationCommand
Apply available updatesupgrade, after refresh and plan review
Reverse the most recent committed transactionundo, after checking history and its dry run
Restore one package to a particular older versiondowngrade <package> <version>
An operation was interrupted and is pendingrecover, then verify

Version reversal changes package payloads. It does not reverse registry state, runtime or user data, or setup performed by feature scripts.

For the Peios edition itself, use Upgrading Peios. Its plain CLI also reconciles release seeds after a no-op or declined package request; peipkg's exit 0 is not a cancellation signal to that wrapper. Use upgrade-peios --check to preview without staging or applying seeds.

Refreshing repository metadata #

peipkg refresh [repository]...

peipkg plans against a local, verified copy of each repository's metadata. That copy does not update itself. peipkg refresh is what updates it: for every configured repository — or just the ones you name — peipkg fetches the current signed descriptor and index, verifies them, and replaces the cached copy.

$ peipkg refresh
refreshed "official"
refreshed "internal"

Refresh has two properties worth knowing:

  • Repositories are independent. If one repository is unreachable or fails verification, peipkg reports it and carries on with the rest. One bad repository never blocks a refresh of the others.
  • A failed refresh changes nothing. If a repository cannot be refreshed, peipkg keeps the metadata it already had. It never falls back to unverified or stale-but-unchecked content. The worst a failed refresh does is leave you on yesterday's view.

What "verified" means here — signing keys, freshness floors, the handling of an unsigned repository — is the subject of Repositories and trust.

Run refresh before an upgrade. An upgrade plans against cached metadata, so without a recent refresh it cannot consider newer releases that the cache does not contain. The selected version still depends on the request, source preferences and constraints.

Skip it for long enough and peipkg stops waiting for you: an install, upgrade, or downgrade against a repository whose trust state has passed its maximum trusted age (30 days by default) refreshes that repository itself, and refuses to proceed against one that stays stale — unreachable, or frozen on an unchanging index — unless you pass --allow-stale. The bound and its configuration are covered in Repositories and trust.

Upgrading #

peipkg upgrade [package]...

With no arguments, upgrade considers every installed package in the current root and its reachable named roots for a newer version that satisfies resolution. With package names, it considers those packages in each reachable root where they are installed, including any new dependencies they need. --no-recurse confines resolution and execution to the current root.

$ peipkg refresh && peipkg upgrade
the following changes will be made:
  upgrade    zlib 1.3.1 -> 1.3.2
  upgrade    nginx 1.27.4 -> 1.27.5
proceed? [y/N]

upgrade uses the same plan-and-confirm flow as install — peipkg shows the full set of changes and waits for approval — and the same options:

OptionEffect
--dry-runPrint the plan and stop. A good way to preview what an upgrade would move.
--yes, -ySkip the proceed? prompt.
--no-recurseConfine the upgrade to the current root only — disable the cascade into nested named roots.
--allow-staleProceed although a repository's trust state exceeds its maximum trusted age. Warned and audited.

By default, upgrade resolves one combined plan over the current root and its reachable named roots. One approval covers that plan. If it changes more than one root, peipkg coordinates the participants as a cross-root transaction, not independent per-root upgrades. Preparation failure attempts rollback; a later commit failure can leave some roots committed and others pending. Read the named-root transaction boundaries and cross-root recovery before treating a failed operation as unchanged. This describes peipkg 8b588ae8's upgrade entry and single approval/executor selection; check the revision supplied by your image.

If the plan contains no updates, peipkg says so and exits. That is a result against the available metadata and constraints, not proof that every upstream release is installed.

Downgrading #

peipkg downgrade <package> <version>

downgrade moves one package to a specific older version. You name the package and the exact version you want:

$ peipkg downgrade nginx 1.27.4

Older versions are not in a repository's active index — that index lists current versions only. They live in its archive index, which peipkg fetches on demand when you ask for a version that is not current. The package must still exist in some configured repository's archive for the downgrade to be possible.

A downgrade is treated as a deliberate move. Going backward — onto a version that may have known issues a newer one fixed — is one of the actions peipkg flags for explicit authorisation: beyond the routine proceed? prompt, peipkg asks you to authorise the specific downgrade, and --yes does not stand in for that answer. See Elevated authorisation for the full set of actions that work this way.

downgrade accepts --dry-run, --yes, -y, and --allow-stale with the same meaning as elsewhere.

Undoing the last change #

peipkg undo

Before applying undo, identify the most recent committed transaction:

peipkg history
peipkg undo --dry-run

undo reverses the most recent committed transaction. If that transaction installed a package, undo removes it; if it upgraded, downgraded, or removed packages, undo restores each one to the version it had before.

$ peipkg undo
undoing transaction 47 (upgrade nginx, zlib)
the following changes will be made:
  downgrade  nginx 1.27.5 -> 1.27.4
  downgrade  zlib 1.3.2 -> 1.3.1
proceed? [y/N]

Check that the old packages are available before relying on undo. The technical reference describes archive-based resolution requiring a reachable repository or usable cache; it does not promise retained transaction backups. Even where undo is exempt from freshness gating, that does not guarantee it can fetch an old version offline.

Be precise about what undo is. It is not a rollback of committed state — the previous transaction happened and stays in the history. undo computes the inverse of that transaction and applies it as a new transaction of its own. The history grows; it does not rewind. That new transaction can itself be undone, and so on.

Because restoring an older version is a backward move, undo carries the same explicit-authorisation requirement as downgrade for any package it walks back. It accepts --dry-run and --yes, -y.

To undo something other than the most recent transaction, or to see the history undo works against, use peipkg history — and revert a specific package directly with downgrade.

The routine cycle #

For day-to-day maintenance the loop is:

$ peipkg refresh        # learn what is available
$ peipkg upgrade --dry-run   # preview the move
$ peipkg upgrade        # apply it

downgrade and undo are the recovery commands — use them when an upgrade has brought in a change you want to remove. They apply a new package transaction. Read the recovery limits before relying on another reversal, and verify after a failed or interrupted attempt.

Exit status #

CodeMeaning
0The operation succeeded — including a dry run, a plan with nothing to do, and a declined prompt or authorisation (nothing failed).
1The operation failed — a repository could not be refreshed, a repository's trust state exceeded its maximum age and a forced refresh could not clear it, resolution or a download or verification failed, cross-root preparation, commit or recovery failed, there is no committed transaction to undo, or a command's arguments were wrong (downgrade without a package and version, an unparsable version, a malformed option).
2A usage error before any command ran — no command, an unknown command, or a malformed global option (including a --root reference that does not resolve).

Edit this page