Platform families and the portable build model
Version: 0.1
1. Purpose
Every Unix-family system is constructed by the same sequence of decisions. Only the vocabulary, the packaging format and the privilege requirements differ. This document defines that sequence as a portable model, maps it onto each platform family, and states the contract an adapter must satisfy to be admitted to a construction service.
The model exists so that a specification expresses intent — a hardened kiosk, a branded desktop, a signed appliance image — and the adapter supplies the mechanics. Where intent cannot be expressed portably, the platform-specific part is explicit rather than hidden.
2. The canonical construction pipeline
| Stage | Name | Obligation |
|---|---|---|
| S1 | Resolve specification | expand the profile, base and overrides into one effective, canonical description |
| S2 | Pin sources | bind every origin to an immutable archive state and an authenticated trust anchor |
| S3 | Resolve closure | compute the exact set of inputs with versions and digests; this and S1–S2 produce the lock |
| S4 | Bootstrap | create the minimal root from authenticated inputs, or, for source-first systems, build the toolchain |
| S5 | Populate | install the intended content, or build world and kernel into a staging tree |
| S6 | Overlay | apply files, branding, policy and configuration owned by the producer |
| S7 | Configure | run declared hooks; establish identity, defaults, users, services and security policy |
| S8 | Boot assembly | kernel, initial ramdisk, bootloader, unified images, measurement inputs |
| S9 | Materialise | build filesystems, partitions and the distributable containers: image, disk, archive, package set |
| S10 | Attest and sign | manifest, bill of materials, provenance, digests and signatures |
Two gates cut across the pipeline:
- V1 — offline verification, after S9: everything that can be checked by reading the produced artefacts.
- V2 — dynamic verification, after S10: boot, update and rollback checks in an environment with firmware, and on reference hardware before general availability.
Stage contracts:
- S1–S3 MUST be side-effect free and MUST be executable without building. The ability to produce and inspect a lock without a build is what makes cost, change review and policy checking possible before resources are spent.
- S4–S9 MUST be executed inside the isolation boundary defined by
SCF-BLD-002. - S10 MUST NOT execute inside the build boundary. Signing keys never enter a
build environment (
SCF-CRY-003).
3. Portable entity model
| Portable entity | Meaning |
|---|---|
| Origin | a named, authenticated place inputs come from |
| Pin | the immutable state of an origin at a moment in time |
| Component | one unit of installable content |
| Selection | the requested set of components, expressed by intent where possible |
| Closure | the resolved set including dependencies, with versions and digests |
| Overlay | producer-owned files placed on the tree |
| Hook | producer-owned code executed at a defined stage |
| Layout | partitions, filesystems and their parameters |
| Boot set | kernel, initial ramdisk, loader and their signatures |
| Installer contract | the mechanism and answer file that installs onto a target |
| Manifest | the machine-readable description of what was produced |
| Attestation | signed evidence about how it was produced |
3.1 Mapping across families
| Portable entity | deb | rpm | apk | FreeBSD | OpenBSD | NetBSD | illumos | Nix / Guix | Yocto / Buildroot |
|---|---|---|---|---|---|---|---|---|---|
| Origin | sources.list / deb822 .sources | .repo baseurl | /etc/apk/repositories | pkg repo conf | mirror + set path | pkgsrc + release path | IPS publisher | substituter / channel | SRC_URI, layer git |
| Pin | archive snapshot service | immutable compose or private snapshot | none upstream; producer-held mirror | release branch + pkg repo snapshot | release tag | release tag | publisher timestamp | flake.lock rev / channel commit | layer commit |
| Component | .deb | .rpm | .apk | .pkg (and, with pkgbase, base itself) | set tarball | set tarball | IPS FMRI | derivation | recipe |
| Selection | task, metapackage, package list | comps group, blueprint packages | profile apks= | pkg list, src.conf knobs | set list | set list | package list | module / manifest | IMAGE_INSTALL |
| Closure | apt solver output | libsolv output | apk solver output | pkg solver output | fixed set | fixed set | IPS solver | derivation graph | task graph |
| Overlay | includes.chroot | kickstart files, image customisations | apkovl | poudriere overlay dir | siteXX.tgz | METALOG-aware staging | manifest actions | module files | ROOTFS_POSTPROCESS |
| Hook | chroot hooks | %post, postprocess script | .post-install | pre/post image scripts | install.site | postinstall scripts | actuators; no install scripts by design | activation script | postprocess command |
| Layout | image build stage | partition stages | image profile | poudriere image type | disklabel template | build.sh image targets | distro constructor | image.repart / image type | wic kickstart |
| Boot set | signed shim, loader, kernel packages | signed shim, loader, kernel packages | kernel flavours | loader.efi | bsd, bsd.rd | kernel sets | boot archive | unified images | EFI_PROVIDER |
| Installer contract | preseed / autoinstall answer file | kickstart | setup-alpine answers | installerconfig | install.conf autoinstall | none — image-first only | distro constructor manifest | declarative config | none — image-first only |
| Signing | repository-level | package-level plus repository metadata | index and package prefix signature | repository signature or fingerprint | signed digest file per set | digest files | per-package X.509 signature | per-artefact signature | producer-defined |
Two structural differences matter more than the vocabulary:
Binary-first versus source-first. In the deb, rpm and apk families the unit
is a pre-built package and the base is composed by resolving packages. In the
BSD and source-based families the base is a single tree built as one unit, and
"packages" are a way of slicing the result. Consequences: S4–S5 are cheap and
parallel in the first case and expensive and indivisible in the second; S9 is a
dependency-resolution problem in the first case and a straightforward staging
problem in the second. The families are converging — FreeBSD pkgbase turns the
base into packages, IPS and hpkg were always package-shaped — but a portable
model must accommodate both.
Installer-first versus image-first. Some families ship an installer that is scripted by an answer file. Others have no scripting facility and are installed by writing a prepared image. An adapter MUST declare which model it supports; a profile that requires unattended installation cannot be satisfied by an image-first adapter without an additional first-boot mechanism.
4. Family dossiers
Each dossier states what the family gives the producer for free, what it demands, and where its sharp edges are.
4.1 deb
Composition engines: the Debian live builder, which produces a combined live
and installer image; debootstrap, still the reference bootstrapper of the
installer and the build daemons, and the alternative implementation
mmdebstrap with the layered YAML wrapper bdebstrap; debos for
recipe-driven images inside a disposable virtual machine; FAI, which also
produces both installer and live media; and mkosi for disk, unified-kernel
and OCI outputs.
Ubuntu composes with a fork of the live builder driven by seed expansion; its
build service is not open to third parties.
Strengths: the largest archive, an archive snapshot service for Debian and Ubuntu, the strongest reproducibility programme of any family, and a signed boot chain that a derivative inherits for free as long as it does not rebuild it.
Sharp edges: the live builder requires privilege and has no unprivileged path; downstream archives built on the older repository tooling lack index content-addressing, which means a caching proxy in front of them will produce intermittent index mismatches; package files are not signed in Debian practice, so per-file integrity derives from digests in the signed index and trust depends on index freshness.
4.2 rpm
Composition engines: the Fedora compose tooling for full distribution composes,
osbuild with declarative blueprints and a manifest of stages for cloud and
disk images, KIWI for appliance and ISO descriptions, rpm-ostree for
commit-based systems with a lockfile that pins exact package versions, and
bootc for systems defined as container images. The ALT Linux mkimage
profile system is the most interesting declarative distribution builder in this
family and pairs with an unprivileged two-user build sandbox.
Strengths: package-level signatures independent of the repository; a mature kickstart contract for unattended installation; the strongest formal-compliance ecosystem, with hardening profiles and automated scanning content maintained against the same content project used by certification programmes.
Sharp edges: no general per-day archive snapshot service, so a producer that needs pinning must maintain its own immutable mirror; repository metadata is not always signed by default even where packages are; on-premises image tooling has historically been limited to building the same operating system family as the build host, which forces a worker pool per family.
4.3 apk
Composition engines: the Alpine image scripts with named profiles and an overlay archive applied at first boot; and, outside Alpine proper, a declarative pair of tools that build packages and then assemble container images with no imperative step at all, producing bit-for-bit identical output and a bill of materials for every build.
Strengths: the smallest images, the simplest overlay mechanism, and a family in which a fully unprivileged, byte-reproducible image build is the normal path rather than an achievement — matched only by the declarative source-based systems.
Sharp edges: no archive snapshot service, so pinning requires a producer-held mirror; the signature scheme carries no revocation or expiry semantics, and in practice a repository is trusted through a single key file; the package format is mid-transition, so tooling assumptions should be version-checked.
4.4 FreeBSD
Composition: a documented release build from the source tree driven by a single configuration file, producing installer media, memory-stick images, virtual machine images and cloud images; a jail-based bulk builder that produces a private package repository and can also emit images; a minimal read-only appliance framework with A/B firmware slices; and an installer that is scripted by a configuration file placed on the media.
Strengths: as of the current release the base system builds reproducibly and without root privilege; boot environments give a first-class rollback primitive; the base can now be delivered as packages, which brings the family much closer to the portable model.
Sharp edges: there is no signed loader accepted by mainstream firmware signing authorities, so verified boot requires enrolling the producer's own keys; the classic base updater and the package-based base are mutually exclusive; the package-based path does not create a boot environment automatically, so rollback must be arranged by the producer.
4.5 OpenBSD
Composition: a strictly ordered kernel-then-userland build producing a fixed set of tarballs and a memory-disk installer image; customisation is deliberately narrow and consists of a site tarball unpacked last and an install script executed in the new root; unattended installation is driven by a question-and-answer file.
Strengths: the strongest default mitigations of any family, a very small trust base for updates built on a single signature tool with a forward key chain, and an unusually simple release artefact set.
Sharp edges: there is no reproducible-build programme; the binary patch tool works only on unmodified official releases, so a derivative that rebuilds the base loses it; the project supports only its own kernel configurations, so a customised kernel forfeits the project's own security machinery.
4.6 NetBSD
Composition: a single build script that cross-builds a complete release — including installable images — from any POSIX host, unprivileged, using a metadata log instead of real file ownership.
Strengths: the best unprivileged and cross-platform build story in the whole Unix family, and reproducible builds available through a build switch.
Sharp edges: the installer has no answer-file facility, so unattended deployment must be image-first; the package system's signing facilities exist but are not enabled by default, so an end-to-end signed channel must be built by the producer.
4.7 Other Unix
DragonFly BSD builds releases from a dedicated tree and has an excellent snapshot-capable filesystem, but no integrated boot-environment mechanism. illumos distributions compose from an XML manifest, sign packages with an X.509 chain and have boot environments integrated with the package manager, which makes them the most complete rollback story of the non-Linux systems; note that the packaging system deliberately has no install scripts, so customisation is expressed as declarative actions and actuators rather than as hooks. Haiku builds with its own tool and mounts packages read-only to form the system. Darwin is a special case: the open parts can be built, but no useful derivative can be produced and redistribution of the shipping system is prohibited.
4.8 Source-based and image-first Linux
Gentoo's release builder pins the package tree by commit and builds through staged bootstraps. Nix and Guix describe the whole system declaratively and pin by lock file or by a time-machine commit, giving the strongest pinning guarantees available anywhere; Guix additionally bootstraps from a minimal seed. Yocto and Buildroot are a different class: the unit is a recipe compiled from source with a cross toolchain and the target usually has no package manager at all, which makes updates whole-image by construction. Their caching differs sharply: one has a content-addressed task-level cache that makes incremental rebuilds cheap, the other has none.
5. Privilege matrix
| Capability | Available unprivileged? |
|---|---|
| Create a root filesystem from packages | yes, in several families, using user namespaces or a build sandbox |
| Populate a filesystem image from a directory | yes, using tools that write filesystems without mounting |
| Build a squashfs or an ISO | yes |
| Mount a block-backed filesystem, attach a loop device, create device nodes | no — requires privilege in the initial namespace |
| Register a foreign-architecture interpreter | no — a host-level, one-time operation |
| Build a combined live and installer image in the deb family | no |
| Cross-build a complete NetBSD release | yes |
| Build a FreeBSD release | yes, in the current release |
| Build an OpenBSD release | effectively no |
Two consequences follow. First, unprivileged construction removes a class of
accidents but is not the isolation boundary; the boundary is the virtual
machine (SCF-BLD-002). Second, an adapter MUST declare its privilege needs
as a capability, because they determine which worker class can run it.
6. Archive pinning
| Family | Pinning available |
|---|---|
| Debian, Ubuntu | public archive snapshot services with time-addressed access |
| Arch | daily public archive |
| Gentoo | tree pinned by commit |
| Nix, Guix | lock file revision; a time-machine that reconstructs the whole toolchain |
| Fedora, RHEL and derivatives | no general per-day service; producer-held immutable mirrors, frozen minor streams and archived end-of-life trees |
| Alpine | none upstream |
| Kali, Mint and similar downstreams | frozen snapshot branches at best |
| BSD | release branches; ports and packages require a producer-held snapshot |
Where the platform provides no service, SCF-SRC-004 obliges the producer to
maintain its own immutable snapshot. The practical form is a content-addressed
mirror of exactly the inputs a lock consumed, retained for the support period,
which simultaneously satisfies source-availability obligations.
7. Signing models
| Model | Families | Implication |
|---|---|---|
| Repository-level | deb | the index is the trust root; index freshness and content-addressed index paths matter operationally |
| Package-level plus metadata | rpm | a package remains verifiable outside its repository; metadata signing must be checked separately |
| Prefix segment on the archive | apk | simple and fast; no expiry or revocation semantics |
| Signed digest manifest per release | OpenBSD | very small trust base; verification happens before unpacking |
| Digest manifest without a default signature | NetBSD | signing facilities exist but are not enabled by default; the producer must supply the signed channel |
| Repository fingerprint or public key | FreeBSD | the trust anchor is a fingerprint file set shipped with the system |
| Per-package certificate chain | illumos | supports policy levels up to mandatory signature enforcement |
| Per-artefact signature over content address | Nix, Guix, OCI | trust attaches to content, not to a location |
An adapter MUST expose the family's model as a capability so that
SCF-ART-004 and SCF-UPD-004 can be verified rather than assumed.
8. The adapter contract
An adapter is admitted only if it implements the following and declares its capabilities honestly.
Operations
| Operation | Requirement |
|---|---|
describe | return capabilities: outputs, architectures, privilege class, pinning support, signing model, installer contract, reproducibility class |
validate | check a specification against the family schema without side effects |
resolve | produce a lock from a specification without building |
build | execute S4–S9 inside the boundary, from a lock only |
collect | emit artefacts, manifest, bill of materials and log |
Invariants
These are not new obligations. Each restates a Constitution requirement in adapter terms, and is verified through it.
| # | Invariant | Constitution |
|---|---|---|
| 1 | resolve is deterministic for a given specification and pin | SCF-SPC-002, SCF-SRC-004 |
| 2 | build consumes only the lock and does not re-resolve | SCF-SPC-003, SCF-REP-001 |
| 3 | build requires no network access beyond the declared mirrors | SCF-BLD-004 |
| 4 | build signs nothing | SCF-CRY-003 |
| 5 | every artefact is reported with its digest and role | SCF-ART-001 |
| 6 | failure is a structured result identifying the stage | SCF-BLD-008 |
| 7 | declared capabilities are verified by conformance tests, not trusted | SCF-EVD-001 |
Attestation is produced by the control plane from the build record, not inside
the build environment (SCF-ART-003, SCF-CRY-003).
9. Choosing an approach
| Requirement | Approach |
|---|---|
| Support a distribution whose build pipeline is closed or inseparable from its vendor | remaster the official image; this is the only path for several major desktop distributions and it preserves the inherited boot chain |
| Combined live and installer media in the deb family | the Debian live builder, inside a virtual machine |
| Disk, root filesystem, container or unified-kernel outputs | an unprivileged package-to-filesystem toolchain |
| Strongest possible pinning and reproducibility | a fully declarative source-based system |
| Appliance with atomic update and rollback | an image-first system with A/B or commit-based deployment |
| BSD appliance | the family's own release tooling plus a producer-held package repository |
10. Known impossibilities
State these in the product profile rather than discovering them late.
- A combined live and installer image cannot currently be produced without privilege in the deb family.
- A derivative that rebuilds the kernel or the bootloader cannot inherit an upstream signed boot chain.
- Obtaining a signed boot component from a mainstream signing authority is a
multi-quarter process with a substantial refusal rate and hard
organisational prerequisites; a product plan MUST NOT depend on it
(
SCF-BOOT-005). The measured figures, their method and their date are recorded in the platform research dossier, not here. - Bit-for-bit reproducibility is not achievable for every family; several have
no archive service and no reproducibility programme (
SCF-REP-002). - Enrolling a producer platform key on consumer firmware in user mode requires physical presence at the machine by design. Managed platforms may permit remote provisioning or factory pre-enrolment; the product profile MUST state which case applies.
- Some families have no unattended-installation contract; those profiles must be image-first.