Build pipeline

From configuration to running system

  1. 01

    Hosts and features

    A host file lists its features; features declare packages, services, files and security settings. Everything is validated before anything changes.

  2. 02

    Sources and verification

    Each package is fetched prebuilt from an ordered list of sources, or built from its definition. Signatures, sizes and hashes are checked on the way in.

  3. 03

    Assessment

    Built-in checks and any enabled scanners run against the unpacked package. Your [security] policy approves it, warns, or holds it in quarantine.

  4. 04

    Content-addressed store

    Approved files are stored once under their content hash, with a reference count per file.

  5. 05

    Sealed generation

    The store is composed into a composefs image with SELinux labels and an fs-verity seal, plus a boot entry.

  6. 06

    Activation

    nexis-init starts the generation’s services in dependency order, each in its declared sandbox, and supervises them.

Components

NexisOS is written in Nim. Each program has a narrow job and its own SELinux domain.

nexis

The system manager and CLI. Reads the configuration, fetches, verifies and builds packages, composes and switches generations, and collects garbage.

nexis-init

PID 1. Loads SELinux policy before any service, supervises services through pidfds, applies each service’s sandbox, and runs scheduled services.

nexis-guard

Reads the firewall’s log and the security events nexis records: bans scanners, brute-force sources and servers that sent tampered packages, and reports drift.

Installer ISO

Throwaway media built with Buildroot, carrying the TUI installer. The installer is never installed on the target.

Scope boundaries

Separate programs keep PID 1 free of package-handling code, and let SELinux confine each one by its file label.

Component Responsible for Not responsible for
nexis Packages, security policy, users, files, generations, garbage collection Running services; building installation media
nexis-init Boot, SELinux policy load, service supervision and sandboxing, schedules, shutdown Package or configuration management
nexis-guard Bans from firewall logs and package events, /etc drift and set-ID reports Writing configuration; deciding what is installed
Installer ISO Partitioning, writing the first host file, the first generation Anything after installation finishes

Key design decisions

Each is recorded, with the reasoning and the alternatives, in the project docs.

TOML, and files for everything else

The schema covers only what is stable: hosts, disks, boot, users, features. An application’s config stays in its own format as a real file, so nothing breaks when upstream adds an option.

The store is not the runtime

Generations are mounted composefs images over the store, so /usr is a normal directory tree. No symlink farm, no store paths in RPATH.

Deduplicate on write

Objects are named by their content hash, so a second copy is never written. There is no optimise command because there is nothing to optimise.

Reference counts, not mark-and-sweep

Retiring a generation touches only that generation’s files. Collection cost follows what changed, not the size of the store, and deletes go out in one batch.

No SQLite

The reference index is an append-only log loaded into a hash map; package records are small files. LMDB is the documented step up if a store ever needs it.

Labels belong to the generation

SELinux labels live in each generation’s image, not on shared store files, so deduplication and per-generation labelling never conflict.

Trust and findings are separate

Signatures and hashes decide trust; scanners can only add findings that block. No scanner can vouch for a package.

Separate binaries

nexis, nexis-init and nexis-guard stay separate programs so each gets its own SELinux domain and PID 1 stays small.

Buildroot for the ISO

Installation media is built with Buildroot, kept entirely outside nexis.