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

Reference

Single-page view · as markdown

The spec

Peios / Peiso / Reference

A spec is a TOML file. Unknown keys are errors. Relative paths resolve against the spec file's directory, not the current directory — which is also what lets several specs be layered into one.

[[packages.repository]]
url  = "file://../../pkgs/_pkgsOut_/"
keys = ["../../pkgs/dev-signing.pub"]

[baseline]
edition     = "Experimental"
package     = "dev.peios.peios-experimental"
version     = "2026.8"
first_boot  = "live"
source_date = "2026-06-22T00:00:00Z"

[devtools]
dwe = false

[registry]
add    = []
remove = []

[[package]]
name    = "org.gnu.bash"
version = ">= 5.2"
root    = ""

[[file]]
src  = "overlay/motd"
dest = "usr/etc/motd"
sddl = "O:SYG:SYD:(A;;GA;;;SY)(A;;FR;;;WD)"

[[autorun]]
src  = "scripts/setup.sh"
name = "50-setup"

[[feature]]
name  = "dynamic-boot"
state = "enable"

[[medium]]
src  = "docs/"
dest = "docs"

[squashfs]
compression = "zstd"
exclude     = []

[initramfs]
exclude = ["var/state/peipkg", "lcl/conf/peipkg"]

[boot]
cmdline_extra = ""

Layering #

A build may name several specs, and they are layered left to right:

peiso root shared.toml profiles/kernel-only/peiso.toml

Each file is read and resolved on its own first, against its own directory. A file:// repository URL, a [[file]] src, an [[autorun]] script: each means what it says where it is written, so a layer stays movable and two layers in different directories can each name paths beside themselves.

Only the layering as a whole has to be a complete spec. The two requirements no single file can be held to — an edition, and at least one repository — are checked after the merge, and the error names every layer rather than guessing which should have carried the key. So this is a spec:

# shared.toml — where packages come from. A property of the checkout.
[[packages.repository]]
url  = "file://../pkgs/_pkgsOut_/"
keys = ["../pkgs/dev-signing.pub"]
# profiles/kernel-only/peiso.toml — what is being built. A property of
# this one build.
[baseline]
edition    = "kernel-only"
first_boot = "none"

…while neither file is one alone. That split is the point: many builds can share one statement of where packages come from without repeating it, and without a build's own file having to restate anything it does not care about.

What a layer does to the one below #

ScalarsA layer that states one overrides; a layer silent about one leaves it alone. edition, package, version, first_boot, source_date, squashfs.compression, squashfs.level, boot.cmdline_extra, devtools.dwe.
ListsAccumulate in layering order: [[packages.repository]], [[package]], [[file]], [[autorun]], [[feature]], [[medium]], registry.add, registry.remove, squashfs.exclude. Repositories are searched in that order, so a base layer's sources come before a later layer's additions.
initramfs.excludeReplaces rather than accumulates. Absent and empty already mean different things there — the default list, and nothing — and appending would leave a layer no way to write either.

A single spec is just a layering of one, so nothing above changes what one file on its own means.

[[packages.repository]] #

Where packages come from. At least one is required; several are searched together, in order.

Key
urlrequiredA file:// path or an http(s):// URL. A relative file:// path is resolved against the spec's directory. A file:// directory holding a repository descriptor (repo.json) is used as a repository; one holding only .peipkg files is used as a directory of packages.
keysoptionalPublic key files (raw 32 bytes or PEM) of the signers of this source's packages. The medium repository must list a package's signer to carry it, and a plain directory of packages publishes no keys of its own — so a pool source needs this.
trust_anchorsoptionalKey fingerprints to verify a repository source against. Ignored for a directory of packages.

A source is where the build gets its packages, and only sometimes where the image will get more. An http(s):// repository is written into the image's repository configuration as source<N>, numbered in declaration order. A file:// one is not: it is a path on the build machine. See the build pipeline.

[baseline] #

Key
editionrequiredThe edition name as written on the box: "Experimental".
packageoptionalThe concrete package identity backing the edition, such as "dev.peios.peios-experimental". New qualified editions should always state it. If omitted for an older spec, Peiso derives the historical name as peios- plus the edition lowercased with whitespace replaced by hyphens: "Pro Desktop" → peios-pro-desktop.
versionoptionalThe edition version to build, e.g. "2026.8". Absent means the newest available. Written without the packaging revision; 2026.8 matches 2026.8-1 and any later revision.
first_bootoptional, default "live"What the medium boots into. "live" adds live-boot to the root. "none" says the composition is not a medium at all and adds no boot flavour — for a root something else will boot, or make bootable its own way; peiso iso refuses it. "install" is reserved and currently refused.
source_dateoptionalAn RFC 3339 timestamp stamped on everything the build produces — compose's source date, the repository indexes, every squashfs entry, the ISO. Absent means the build time, which is not reproducible.

[devtools] #

Key
dweoptional, default falseAdd the Developer Workstation Environment: dev.peios.dwed in the root and the live-only dwed-service seed. The package is listed as medium-only and removed from the installed target by either installer. The build directory and ISO gain a -dwe suffix. A DWE image is ownable by whoever can reach its vsock; it is for development.

[registry] #

Adjust the seeds the edition auto-applies. Names are seed names — login-console, not login-console.reg — resolved to /usr/share/regim/<name>.reg in the composed root.

Key
addoptionalSeeds to stage in addition to the release's. Each must be shipped by a package in the root; a name nothing ships is an error.
removeoptionalSeeds from the release's list (or from add, or the DWE seed) not to stage.

The starting list comes from the edition's release.toml, not from the spec. A spec never has to name a seed the release already applies.

[[package]] #

A package to carry beyond the edition. Repeat the table for each.

Key
namerequiredThe package name, resolved from the spec's sources with its dependencies.
versionoptionalA constraint in peipkg's grammar — "5.2", ">= 5.2", ">= 5.2, < 6". Absent means any version, newest wins.
rootoptional"initramfs" to place the package in the initramfs root — an extra boot hook, say. Absent means the main root.

An addition rides on the same resolution as the edition, so a package that conflicts with the edition's closure fails the build rather than quietly displacing something. There is no way to remove a package: the edition's closure is what makes the image a Peios, and everything else is here only because a [[package]] put it there.

[[file]] #

A file injected into the root, outside any package. Customising an image discusses the cost.

Key
srcrequiredHost path, relative to the spec; must exist and be a file.
destrequiredPath inside the root: relative (a leading / is dropped), cleaned, and not escaping the root.
sddloptionalThe file's security descriptor in SDDL, written into the image as security.peios.sd. Refused for a dest under boot/initramfs/.

[[autorun]] #

A script placed executable in /lcl/policy/autorun.d/.

Key
srcrequiredHost path, relative to the spec.
nameoptional, default the file's nameThe entry's name in the directory; ordering is by name. peiso's own entries are 10-apply-seeds.sh and 20-features.sh.

[[feature]] #

Key
namerequiredA feature under /libexec/features/, present in the root.
stateoptional, default "enable""enable" runs feat add (install then enable); "install" runs feat install only.

[[medium]] #

A file or directory placed in the ISO's data area, reachable at /media/peios/<dest> on the live system.

Key
srcrequiredHost path, relative to the spec; a file or a directory. Symlinks are refused — an ISO9660 data area cannot carry them.
destrequiredPath on the medium, relative and cleaned.

[squashfs] #

Key
compressionoptional, default "zstd"Passed to mksquashfs -comp.
leveloptional, default the compressor's ownPassed to mksquashfs -Xcompression-level; must be a level the chosen compressor accepts. A low level trades image size for build time — the knob a dev layer sets, never a release.
excludeoptionalRoot-relative paths left out of the image (a directory takes its subtree).

[initramfs] #

Key
excludeoptional, default ["var/state/peipkg", "lcl/conf/peipkg"]Globs, relative to the initramfs root, that mkirf leaves out. Setting it replaces the default; [] excludes nothing.

[boot] #

Key
cmdline_extraoptionalAppended to the kernel command line the boot package ships, and baked into the UKI. There is no full replacement.

What the spec cannot say #

No package list, no output paths, no ISO label, no full command-line replacement. Everything the spec adds — packages, files, scripts, features, medium contents — is an addition to a release, recorded in customisations.toml; nothing in it can redefine what the release is, and nothing in it can quietly produce a different image from the same file. What a Peios contains is the edition package's to say; peiso builds what it says, plus what you asked for on top.

The build directory

Peios / Peiso / Reference

Every build writes to one directory, named for what was resolved: dist/peios-<edition>-<version>/, with -dwe appended for a development medium. The version is the edition package's without its packaging revision — 2026.8, not 2026.8-1. The directory is relative to where peiso is run; peiso root --out overrides the root's location only.

A build refuses to run if root/ already exists; --overwrite replaces it (only a composed root or an empty directory — never anything else the output path may name). make iso passes the flag, so rebuilding in place is its normal behaviour.

EntryWritten by
compose.tomlcompose stageThe generated compose manifest: sources, the initramfs root, the edition and extra package requests. Marked "do not edit".
compose.lock.tomlcompose stageThe resolved closure: every package, version, root, source and hash. What the image is, exactly.
root/compose stageThe composed system. root/boot/initramfs/ is the initramfs root; root/var/state/peipkg/ its database; root/lcl/conf/peipkg/ its repository configuration.
sidecars.jsonlcompose stageThe signature sidecars compose recorded instead of stamping: one {path, blob} per line, path relative to root/. Consumed by the squashfs stage.
customisations.tomlcustomise stageEvery file, autorun and feature the spec added, with the host paths they came from.
repo/medium stageThe medium repository: descriptor, indexes, keys, and the disk-boot packages. Copied onto the ISO as repo/.
root/lcl/conf/peipkg/peios-medium.repomedium stageThe client configuration for it, anchored on this build's key.
root/lcl/policy/autoapply.d/*.regseeds stageThe staged seeds.
root/lcl/policy/autorun.d/10-apply-seeds.shseeds stageThe autorun that drains them at boot.
root/system/boot/initramfs.cpio.zstinitramfs stageThe packed initramfs, inside the root.
rootfs.squashfssquashfs stageThe live root filesystem, with signature attributes. Outside root/ so it cannot contain itself.
root/boot/efi/EFI/BOOT/BOOTX64.EFIUKI stageThe unified kernel image. root/boot/efi/ is the ESP tree.
peios-<edition>-<version>[-dwe].isoISO stageThe medium.

The Makefile adds its own files beside the spec, not in the build directory: disk.img (the install target), ovmf-vars.fd (firmware variables, reset on every boot), and console.log from drive.py.

Only the ISO is needed to boot or install. root/ and rootfs.squashfs are kept because they are what you look at when something is wrong; compose.lock.toml is kept because it is the provenance.

Peios Learn — documentation for the Peios project.

Built with Trail.