Composing a root
Use the separate peipkg-compose binary when you need a new package-owned
root directory for an image. Use peipkg to maintain a root that already
exists. Compose does not produce a bootable image by itself or run feature
setup scripts.
Build and check a new tree #
-
Prepare a manifest with the intended architecture, timestamp, repositories, package set and any named roots. Verify the repository anchors through a trusted channel. The manifest reference gives every field and a complete example.
-
Choose an output directory that does not exist. Compose refuses an existing tree; do not point it at a live installation.
-
Resolve and record the package set, then build from that lock:
peipkg-compose lock image.toml peipkg-compose build image.toml --out ./root --locked -
Read the build outcome and warnings. If the build fails or is interrupted, the staging directory is left for inspection; it is not the finished root.
-
Inspect the successful output's package records and files, for example with
peipkg --root ./root listandpeipkg --root ./root verifywhere peipkg is available. Check security metadata required by the image separately.
A fresh tree includes package files, a package database and repository
configuration. It does not include recorded repository trust from the build.
On the booted system, check that configuration and deliberately run
peipkg repo add <name> for each source you choose to trust. Configuration is
not a completed trust ceremony.
The mental model #
lock resolves the package set; build assembles it. Keeping the same manifest,
lock and package bytes makes the selected inputs repeatable. For the resolution,
verification and assembly internals, see the
composition reference.
peipkg-compose lock #
peipkg-compose lock <manifest> [-o <lock>]
Creates a lock without building a tree. image.toml defaults to
image.lock.toml. Only -o selects another lock path; there is no --out
for this verb. See the full lock interface.
peipkg-compose build #
peipkg-compose build <manifest> --out <dir> [--locked | --update]
[--dangerously-bypass-path-restrictions]
[--record-xattrs <file>] [--no-dependencies]
- Use
--lockedto require an existing matching lock and do no metadata resolution. Package bytes must still be available. - Use
--updateto resolve again and overwrite the lock before building. - With neither flag, a missing lock is created; an existing lock must match
the manifest.
--lockedand--updatecannot be combined. --outis required, and its directory must not already exist.
The complete build options explain the explicit
path-restriction grant, recording security attributes, and --no-dependencies.
That last option deliberately creates a tree that is not self-sufficient;
it leaves signature and hash verification enabled and requires a lock made
in the same mode. Do not add it merely to get past a missing dependency.
The manifest #
The manifest is strict TOML: unknown keys, an empty package set, undeclared
repository or root references, and duplicate (root, name) requests are errors.
The complete schema and sample are in the manifest reference.
When preparing the manifest:
- Check the top-level fields for architecture, timestamp and the requested package set.
- Repository entries
also become
.repofiles in the image; those files do not establish trust. - Package entries
choose versions, sources and target roots. There is no manifest-level
default_root; packages can carry their own default placement. - Named-root paths
must be relative, must not escape through
.., and cannot be..
The lock file #
The generated lock pins the package set. Do not hand-edit it or use --update
just to suppress a mismatch without reviewing the changed inputs. See the
lock contract for digest, architecture and timestamp checks.
Elevated actions that would prompt in a live install are emitted as warnings
during unattended composition, so read them before using the image.
Named roots and claims in a composed image #
All roots are built under one output tree. The composer records named roots and selects claim holders for the fresh package set; no installed incumbents exist to preserve. See the detailed rules for deterministic holder selection and relocatable links.
What ends up in the root #
The output contains payloads, var/lib/peipkg/db.sqlite and repository files
under lcl/conf/peipkg/. A successful build renames the whole staged tree into
place. See the output contract before treating
an interrupted build's staging directory as a usable artifact.
What compose does not do #
The outer image builder is responsible for boot integration, runtime caches and feature setup. Compose runs no post-install maintenance steps and emits no audit events. It does not build or sign the packages it consumes.
The references disagree on security-descriptor materialisation; the CLI
interface documents --record-xattrs, while an implementation summary says
no descriptors are materialised. Inspect the attributes or recorded output
needed by your image. The full limitations and interface differences
retain those details rather than assuming either behaviour is universal.
Exit status #
| Code | Meaning |
|---|---|
0 | Success, or help output (-h, --help, help) |
1 | Resolution, verification, fetch, lock or filesystem failure |
2 | Usage error, including a missing manifest or --out, or conflicting flags |
For exact cases and the absence of environment-variable and --version
interfaces, see the complete command reference.