Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

.nornir/build-variants.toml

# holger — .nornir/build-variants.toml — EMITTED, NOT SOURCE.
#
# Generated by `cargo run -p holger-build-thing -- emit` from holger-recipe (the
# Rust `impl BuildThing`: holger-recipe/src/variants.rs for the build variants,
# packaging.rs for the container and installer rows, lib.rs for the feature
# universe and set rules; holger-build-thing is its wasm32 cdylib shim). The code is the one source; this file
# DESCRIBES the build for readers and for the tools that discover a repo by this
# path (the dwarves forge, the build-thing pane, xtask). Editing it changes
# NOTHING: re-emit after changing the code. Do not edit by hand.
#
# Model: variant -> features -> settings/sub-settings -> typ.
#
# The reasoning that used to sit between these rows is in git history
# (`git show ed4e988:.nornir/build-variants.toml`) and, condensed, in the doc
# comments beside each row. New reasoning goes there, never here: a comment
# written in this file is deleted by the next `emit`.

[nornir-build-thing]
schema = 6

[build]
offers = [
    "admission",
    "admit-share",
    "all-formats",
    "allow-meter",
    "appliance",
    "auth-passkey",
    "console",
    "dev-narrate",
    "downstream",
    "downstream-wg",
    "export-push",
    "federation",
    "fetch",
    "fmt-all",
    "fmt-build-thing",
    "fmt-deb",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-maven",
    "fmt-npm",
    "fmt-python",
    "fmt-raw",
    "fmt-rpm",
    "fmt-rust",
    "fmt-znippy",
    "front",
    "full",
    "heimdall",
    "intel-fetch",
    "jobs",
    "meter-guests",
    "metered",
    "migration",
    "mirror",
    "mvp-server",
    "online",
    "paired",
    "pid1",
    "public-site",
    "secure_update",
    "served",
    "sign",
    "supply-chain",
    "sync",
    "testmatrix",
    "wasm-plugins",
]
independent_suites = true

[build.required]
holger-mvp = ["mvp-server"]
holger-mvp-metered = [
    "mvp-server",
    "metered",
]

[build.downstream]
holger = ["skade"]

[[build.variant]]
name = "holger"
package = "holger"
bin = "holger"
profile = "release"
role = "server"
suites = ["MVP"]
default = true

[[build.variant]]
name = "holger-downstream"
package = "holger-downstream"
bin = "holger-downstream"
profile = "release"
manifest_dir = "holger-downstream"
role = "server"
suites = ["MVP"]

[[build.variant]]
name = "holger-cli"
package = "holger-cli"
bin = "holger-cli"
profile = "release"
linkage = "thin"
role = "client"
suites = ["MVP"]
default = true
reaches = ["holger"]

[[build.variant]]
name = "holger-ui"
package = "holger-ui"
bin = "holger-ui"
profile = "release"
manifest_dir = "../holger-ui/crates/holger-ui"
siblings = ["holger-ui"]
linkage = "thin"
role = "client"
suites = ["MVP"]
reaches = ["holger"]

[[build.variant]]
name = "mvp-server-musl"
package = "holger"
bin = "holger-mvp"
features = [
    "mvp-server",
    "appliance",
    "paired",
    "auth-passkey",
    "sign",
    "allow-meter",
    "fmt-raw",
    "fmt-rust",
    "fmt-npm",
    "fmt-maven",
    "fmt-python",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-deb",
    "fmt-rpm",
    "fmt-znippy",
    "fmt-build-thing",
    "sync",
    "jobs",
    "supply-chain",
    "heimdall",
    "admission",
    "mirror",
]
no_default_features = true
profile = "release"
target = "x86_64-unknown-linux-musl"
role = "server"
suites = ["MVP"]

[[build.variant]]
name = "mvp-server-metered"
package = "holger"
bin = "holger-mvp-metered"
features = [
    "mvp-server",
    "appliance",
    "paired",
    "auth-passkey",
    "sign",
    "metered",
    "admit-share",
    "front",
    "wasm-plugins",
    "meter-guests",
    "fmt-raw",
    "fmt-rust",
    "fmt-npm",
    "fmt-maven",
    "fmt-python",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-deb",
    "fmt-rpm",
    "fmt-znippy",
    "fmt-build-thing",
    "sync",
    "jobs",
    "supply-chain",
    "heimdall",
    "admission",
    "intel-fetch",
    "mirror",
]
no_default_features = true
profile = "release"
member = "holger"
role = "server"
suites = ["MVP"]
kind = "service"

[[build.variant]]
name = "mvp-server-musl-metered"
package = "holger"
bin = "holger-mvp-metered"
features = [
    "mvp-server",
    "appliance",
    "paired",
    "auth-passkey",
    "sign",
    "metered",
    "admit-share",
    "front",
    "wasm-plugins",
    "meter-guests",
    "fmt-raw",
    "fmt-rust",
    "fmt-npm",
    "fmt-maven",
    "fmt-python",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-deb",
    "fmt-rpm",
    "fmt-znippy",
    "fmt-build-thing",
    "sync",
    "jobs",
    "supply-chain",
    "heimdall",
    "admission",
    "intel-fetch",
    "mirror",
]
open = ["dev-narrate"]
no_default_features = true
profile = "release"
target = "x86_64-unknown-linux-musl"
role = "server"
suites = ["MVP"]

[build.variant.edges.plugin]
repo = "monetize-impl"
variant = "holger-guest"
typ = "wasm"
lazy = true

[[build.variant]]
name = "mvp-server-musl-metered-narrate"
package = "holger"
bin = "holger-mvp-metered"
features = [
    "mvp-server",
    "appliance",
    "paired",
    "auth-passkey",
    "sign",
    "metered",
    "admit-share",
    "front",
    "wasm-plugins",
    "meter-guests",
    "fmt-raw",
    "fmt-rust",
    "fmt-npm",
    "fmt-maven",
    "fmt-python",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-deb",
    "fmt-rpm",
    "fmt-znippy",
    "fmt-build-thing",
    "sync",
    "jobs",
    "supply-chain",
    "heimdall",
    "admission",
    "intel-fetch",
    "mirror",
    "dev-narrate",
]
no_default_features = true
profile = "dev-media"
target = "x86_64-unknown-linux-musl"
role = "server"
suites = ["MVP"]

[build.variant.edges.plugin]
repo = "monetize-impl"
variant = "holger-guest"
typ = "wasm"
lazy = true

[[build.variant]]
name = "holger-mvp-appliance"
role = "server"
suites = ["MVP"]
kind = "container"
container_ref = "holger-mvp-appliance"

[[build.variant]]
name = "holger-installer"
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "holger-installer-metered"
open = ["dev-narrate"]
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "holger-appliance-iso"
role = "server"
suites = ["MVP"]
kind = "iso"

[[build.variant]]
name = "plugin-allocation"
package = "holger-plugin-allocation-wasm"
profile = "release"
target = "wasm32-unknown-unknown"
linkage = "not-applicable"
role = "library"
suites = ["MVP"]
default = true
kind = "wasm"

[build.variant.sign]
purpose = "plugin"

[[build.variant]]
name = "plugin-skidbladnir"
package = "holger-handler-skidbladnir-wasm"
profile = "release"
target = "wasm32-unknown-unknown"
linkage = "not-applicable"
role = "library"
suites = ["MVP"]
kind = "wasm"

[build.variant.sign]
purpose = "plugin"

[[build.variant]]
name = "plugin-rust-toolchain"
package = "holger-handler-rust-toolchain-wasm"
profile = "release"
target = "wasm32-unknown-unknown"
linkage = "not-applicable"
role = "library"
suites = ["MVP"]
kind = "wasm"

[build.variant.sign]
purpose = "plugin"

[[build.variant]]
name = "estate-front-musl-metered"
package = "holger-estate-front"
bin = "holger-estate-front"
features = [
    "console",
    "metered",
    "public-site",
]
open = ["dev-narrate"]
no_default_features = true
profile = "release"
target = "x86_64-unknown-linux-musl"
manifest_dir = "holger-estate-front"
siblings = [
    "Skidbladnir",
    "draupnir",
    "edda",
    "facett",
    "funnel-core",
    "holger-ui",
    "modgunn",
    "monetize",
    "skade",
    "tunnr",
    "znippy",
    "znippy-zoomies",
]
role = "server"
suites = ["MVP"]
reaches = ["holger"]

[[build.variant]]
name = "estate-front-musl-metered-narrate"
package = "holger-estate-front"
bin = "holger-estate-front"
features = [
    "console",
    "metered",
    "public-site",
    "dev-narrate",
]
no_default_features = true
profile = "dev-media"
target = "x86_64-unknown-linux-musl"
manifest_dir = "holger-estate-front"
siblings = [
    "Skidbladnir",
    "draupnir",
    "edda",
    "facett",
    "funnel-core",
    "holger-ui",
    "modgunn",
    "monetize",
    "skade",
    "tunnr",
    "znippy",
    "znippy-zoomies",
]
role = "server"
suites = ["MVP"]
reaches = ["holger"]

[[build.variant]]
name = "holger-front-installer-metered"
open = ["dev-narrate"]
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "holger-keep"
open = ["dev-narrate"]
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "holger-front-keep"
open = ["dev-narrate"]
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "downstream-musl"
package = "holger-downstream"
bin = "holger-downstream"
features = [
    "pid1",
    "heimdall",
]
profile = "release"
target = "x86_64-unknown-linux-musl"
manifest_dir = "holger-downstream"
role = "server"
suites = ["MVP"]

[[build.variant]]
name = "holger-downstream-oneway-installer"
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.variant]]
name = "downstream-fetch-musl"
package = "holger-downstream"
bin = "holger-downstream-fetch"
features = [
    "fetch",
    "downstream-wg",
    "paired",
    "heimdall",
]
profile = "release"
target = "x86_64-unknown-linux-musl"
manifest_dir = "holger-downstream"
role = "server"
suites = ["MVP"]

[[build.variant]]
name = "holger-downstream-installer"
role = "server"
suites = ["MVP"]
kind = "installer"

[[build.container]]
name = "holger-mvp-appliance"
base = "scratch"
entrypoint = ["/holger-mvp"]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
workdir = "/data"
expose = [
    50051,
    8443,
]
tags = ["holger-mvp-appliance:0.6.9"]
archive = ".container-out/holger-mvp-appliance.tar"

[[build.container.layers]]
dest = "/holger-mvp"
from_variant = "mvp-server-musl"
executable = true

[build.container.env]
HOLGER_APPLIANCE = "1"

[[build.iso]]
name = "holger-appliance-iso"
staging = ".nornir/assets/appliance-root"
volume_id = "HOLGER_APPLIANCE"
boot_params = [
    "console=tty0",
    "console=ttyS0,115200",
    "panic=10",
    "HOLGER_APPLIANCE=1",
    "korp.entry=holger",
    "korp.znippy=/app.znippy",
    "korp.appliance=lean",
    "korp.mode=live",
    "--",
    "start",
    "--config",
    "/holger.ron",
]
format = "uefi"
from_variant = "mvp-server-musl"
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[[build.iso.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.iso.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"

[[build.iso.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.iso.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.iso.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.iso.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[build.iso.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[[build.installer]]
name = "holger-installer"
variant = "mvp-server-musl"
volume_id = "HOLGER_INSTALL"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger",
]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.payload_entries]
"sandbox/bundle-trust.ron" = ".sandbox-out/bundle-trust.ron"
"sandbox/clamav.rootfs.tar" = ".sandbox-out/clamav.rootfs.tar"
"sandbox/crun" = ".sandbox-out/crun"
"sandbox/heimdall-container-shim" = ".sandbox-out/heimdall-container-shim"
"sandbox/heimdall-guests-0.2.1.intoto.jsonl" = ".sandbox-out/heimdall-guests-0.2.1.intoto.jsonl"
"sandbox/heimdall-verify-bundle-decoder.wasm" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm"
"sandbox/heimdall-verify-bundle-decoder.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.blake3"
"sandbox/heimdall-verify-bundle-decoder.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.p7s"
"sandbox/heimdall-verify-bundle-verifier.wasm" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm"
"sandbox/heimdall-verify-bundle-verifier.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.blake3"
"sandbox/heimdall-verify-bundle-verifier.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.p7s"
"sandbox/heimdall-verify-bundle.wasm" = ".sandbox-out/heimdall-verify-bundle.wasm"
"sandbox/heimdall-verify-bundle.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle.wasm.blake3"
"sandbox/heimdall-verify-bundle.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle.wasm.p7s"
"sandbox/holger-scan-worker.rootfs.tar" = ".sandbox-out/holger-scan-worker.rootfs.tar"
"sandbox/manifest.toml" = ".sandbox-out/manifest.toml"
"sandbox/sigstore-trust.holger.znippy" = ".sandbox-out/sigstore-trust.holger.znippy"

[build.installer.env]
HOLGER_APPLIANCE = "1"
HOLGER_CONSOLE_PATH = "/login"
HOLGER_DATA = "/data/holger"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "hub_conf"
label = "Hub declaration (the ceremony hub.conf, public data)"
kind = "text"
required = false
staged_file = "hub.conf"

[[build.installer.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"
lands = "release"

[[build.installer.params]]
name = "plugin_trust_root"
label = "Plugin trust root (korp-root-ca, PEM)"
kind = "text"
required = false
staged_file = "korp-root-ca.pem"
lands = "release"

[[build.installer.params]]
name = "intel_trust_policy"
label = "Intel trust policy (holger.intel/v1 signers, RON)"
kind = "text"
required = false
staged_file = "intel-trust.ron"
lands = "release"

[[build.installer.params]]
name = "bundles_trust_policy"
label = "Bundles trust policy (the signers of published bundles, RON)"
kind = "text"
required = false
staged_file = "bundles-trust.ron"
lands = "release"

[[build.installer.params]]
name = "underlay"
label = "Underlay address (addr/prefix@interface)"
kind = "text"
required = false
boot_param = "korp.env.HOLGER_UNDERLAY"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "pairing_seed"
label = "Pairing seed (nordisk-pairing seed.toml: estate, front, installer CA, bootstrap cert+key)"
kind = "text"
required = false
staged_file = "pairing/seed.toml"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[build.installer.fixtures]
hub_conf = "wg-hub"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-installer-metered"
variant = "mvp-server-musl-metered"
volume_id = "HOLGER_INSTALL_METERED"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger",
]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.payload_entries]
"sandbox/bundle-trust.ron" = ".sandbox-out/bundle-trust.ron"
"sandbox/clamav.rootfs.tar" = ".sandbox-out/clamav.rootfs.tar"
"sandbox/crun" = ".sandbox-out/crun"
"sandbox/heimdall-container-shim" = ".sandbox-out/heimdall-container-shim"
"sandbox/heimdall-guests-0.2.1.intoto.jsonl" = ".sandbox-out/heimdall-guests-0.2.1.intoto.jsonl"
"sandbox/heimdall-verify-bundle-decoder.wasm" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm"
"sandbox/heimdall-verify-bundle-decoder.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.blake3"
"sandbox/heimdall-verify-bundle-decoder.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.p7s"
"sandbox/heimdall-verify-bundle-verifier.wasm" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm"
"sandbox/heimdall-verify-bundle-verifier.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.blake3"
"sandbox/heimdall-verify-bundle-verifier.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.p7s"
"sandbox/heimdall-verify-bundle.wasm" = ".sandbox-out/heimdall-verify-bundle.wasm"
"sandbox/heimdall-verify-bundle.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle.wasm.blake3"
"sandbox/heimdall-verify-bundle.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle.wasm.p7s"
"sandbox/holger-scan-worker.rootfs.tar" = ".sandbox-out/holger-scan-worker.rootfs.tar"
"sandbox/manifest.toml" = ".sandbox-out/manifest.toml"
"sandbox/sigstore-trust.holger.znippy" = ".sandbox-out/sigstore-trust.holger.znippy"

[build.installer.env]
HOLGER_APPLIANCE = "1"
HOLGER_CONSOLE_PATH = "/login"
HOLGER_DATA = "/data/holger"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "hub_conf"
label = "Hub declaration (the ceremony hub.conf, public data)"
kind = "text"
required = false
staged_file = "hub.conf"

[[build.installer.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"
lands = "release"

[[build.installer.params]]
name = "plugin_trust_root"
label = "Plugin trust root (korp-root-ca, PEM)"
kind = "text"
required = false
staged_file = "korp-root-ca.pem"
lands = "release"

[[build.installer.params]]
name = "intel_trust_policy"
label = "Intel trust policy (holger.intel/v1 signers, RON)"
kind = "text"
required = false
staged_file = "intel-trust.ron"
lands = "release"

[[build.installer.params]]
name = "bundles_trust_policy"
label = "Bundles trust policy (the signers of published bundles, RON)"
kind = "text"
required = false
staged_file = "bundles-trust.ron"
lands = "release"

[[build.installer.params]]
name = "underlay"
label = "Underlay address (addr/prefix@interface)"
kind = "text"
required = false
boot_param = "korp.env.HOLGER_UNDERLAY"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "pairing_seed"
label = "Pairing seed (nordisk-pairing seed.toml: estate, front, installer CA, bootstrap cert+key)"
kind = "text"
required = false
staged_file = "pairing/seed.toml"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[build.installer.fixtures]
hub_conf = "wg-hub"

[[build.installer.options]]
name = "dev-narrate"
label = "DEV-NARRATE (sealed early-boot log to the installer, udp/51822) — dev media only"
default = false
feature = "dev-narrate"
forbid_symbols = ["nordisk_narrate"]

[build.installer.options.bakes]
boot_param = "korp.env.NORDISK_MEDIA_KIND"
when_on = "dev"
when_off = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-front-installer-metered"
variant = "estate-front-musl-metered"
volume_id = "HOLGER_FRONT_INSTALL_METERED"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger-estate-front",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.env]
HOLGER_APPLIANCE_DATA = "/data"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "pairing_seed"
label = "Pairing seed (nordisk-pairing seed.toml: estate, front, installer CA, bootstrap cert+key)"
kind = "text"
required = false
staged_file = "pairing/seed.toml"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[[build.installer.params]]
name = "clock"
label = "The front's own clock sources (https://… or ntp://…, comma-separated): the estate's root of time"
kind = "text"
required = false
boot_param = "korp.env.ESTATE_CLOCK"

[[build.installer.options]]
name = "dev-narrate"
label = "DEV-NARRATE (sealed early-boot log to the installer, udp/51822) — dev media only"
default = false
feature = "dev-narrate"
forbid_symbols = ["nordisk_narrate"]

[build.installer.options.bakes]
boot_param = "korp.env.NORDISK_MEDIA_KIND"
when_on = "dev"
when_off = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-keep"
variant = "mvp-server-musl-metered"
volume_id = "HOLGER_KEEP"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger",
    "korp.reinstall=keep",
    "korp.install.then=poweroff",
]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.payload_entries]
"sandbox/bundle-trust.ron" = ".sandbox-out/bundle-trust.ron"
"sandbox/clamav.rootfs.tar" = ".sandbox-out/clamav.rootfs.tar"
"sandbox/crun" = ".sandbox-out/crun"
"sandbox/heimdall-container-shim" = ".sandbox-out/heimdall-container-shim"
"sandbox/heimdall-guests-0.2.1.intoto.jsonl" = ".sandbox-out/heimdall-guests-0.2.1.intoto.jsonl"
"sandbox/heimdall-verify-bundle-decoder.wasm" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm"
"sandbox/heimdall-verify-bundle-decoder.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.blake3"
"sandbox/heimdall-verify-bundle-decoder.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.p7s"
"sandbox/heimdall-verify-bundle-verifier.wasm" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm"
"sandbox/heimdall-verify-bundle-verifier.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.blake3"
"sandbox/heimdall-verify-bundle-verifier.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.p7s"
"sandbox/heimdall-verify-bundle.wasm" = ".sandbox-out/heimdall-verify-bundle.wasm"
"sandbox/heimdall-verify-bundle.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle.wasm.blake3"
"sandbox/heimdall-verify-bundle.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle.wasm.p7s"
"sandbox/holger-scan-worker.rootfs.tar" = ".sandbox-out/holger-scan-worker.rootfs.tar"
"sandbox/manifest.toml" = ".sandbox-out/manifest.toml"
"sandbox/sigstore-trust.holger.znippy" = ".sandbox-out/sigstore-trust.holger.znippy"

[build.installer.env]
HOLGER_APPLIANCE = "1"
HOLGER_CONSOLE_PATH = "/login"
HOLGER_DATA = "/data/holger"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "hub_conf"
label = "Hub declaration (the ceremony hub.conf, public data)"
kind = "text"
required = false
staged_file = "hub.conf"

[[build.installer.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"
lands = "release"

[[build.installer.params]]
name = "plugin_trust_root"
label = "Plugin trust root (korp-root-ca, PEM)"
kind = "text"
required = false
staged_file = "korp-root-ca.pem"
lands = "release"

[[build.installer.params]]
name = "intel_trust_policy"
label = "Intel trust policy (holger.intel/v1 signers, RON)"
kind = "text"
required = false
staged_file = "intel-trust.ron"
lands = "release"

[[build.installer.params]]
name = "bundles_trust_policy"
label = "Bundles trust policy (the signers of published bundles, RON)"
kind = "text"
required = false
staged_file = "bundles-trust.ron"
lands = "release"

[[build.installer.params]]
name = "underlay"
label = "Underlay address (addr/prefix@interface)"
kind = "text"
required = false
boot_param = "korp.env.HOLGER_UNDERLAY"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "pairing_seed"
label = "Pairing seed (nordisk-pairing seed.toml: estate, front, installer CA, bootstrap cert+key)"
kind = "text"
required = false
staged_file = "pairing/seed.toml"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[build.installer.fixtures]
hub_conf = "wg-hub"

[[build.installer.options]]
name = "dev-narrate"
label = "DEV-NARRATE (sealed early-boot log to the installer, udp/51822) — dev media only"
default = false
feature = "dev-narrate"
forbid_symbols = ["nordisk_narrate"]

[build.installer.options.bakes]
boot_param = "korp.env.NORDISK_MEDIA_KIND"
when_on = "dev"
when_off = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-front-keep"
variant = "estate-front-musl-metered"
volume_id = "HOLGER_FRONT_KEEP"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger-estate-front",
    "korp.reinstall=keep",
    "korp.install.then=poweroff",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.env]
HOLGER_APPLIANCE_DATA = "/data"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "pairing_seed"
label = "Pairing seed (nordisk-pairing seed.toml: estate, front, installer CA, bootstrap cert+key)"
kind = "text"
required = false
staged_file = "pairing/seed.toml"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[[build.installer.params]]
name = "clock"
label = "The front's own clock sources (https://… or ntp://…, comma-separated): the estate's root of time"
kind = "text"
required = false
boot_param = "korp.env.ESTATE_CLOCK"

[[build.installer.options]]
name = "dev-narrate"
label = "DEV-NARRATE (sealed early-boot log to the installer, udp/51822) — dev media only"
default = false
feature = "dev-narrate"
forbid_symbols = ["nordisk_narrate"]

[build.installer.options.bakes]
boot_param = "korp.env.NORDISK_MEDIA_KIND"
when_on = "dev"
when_off = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-downstream-installer"
variant = "downstream-fetch-musl"
volume_id = "HOLGER_DOWNSTREAM_INSTALL"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger-downstream-fetch",
]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.payload_entries]
"sandbox/bundle-trust.ron" = ".sandbox-out/bundle-trust.ron"
"sandbox/clamav.rootfs.tar" = ".sandbox-out/clamav.rootfs.tar"
"sandbox/crun" = ".sandbox-out/crun"
"sandbox/heimdall-container-shim" = ".sandbox-out/heimdall-container-shim"
"sandbox/heimdall-guests-0.2.1.intoto.jsonl" = ".sandbox-out/heimdall-guests-0.2.1.intoto.jsonl"
"sandbox/heimdall-verify-bundle-decoder.wasm" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm"
"sandbox/heimdall-verify-bundle-decoder.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.blake3"
"sandbox/heimdall-verify-bundle-decoder.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.p7s"
"sandbox/heimdall-verify-bundle-verifier.wasm" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm"
"sandbox/heimdall-verify-bundle-verifier.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.blake3"
"sandbox/heimdall-verify-bundle-verifier.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.p7s"
"sandbox/heimdall-verify-bundle.wasm" = ".sandbox-out/heimdall-verify-bundle.wasm"
"sandbox/heimdall-verify-bundle.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle.wasm.blake3"
"sandbox/heimdall-verify-bundle.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle.wasm.p7s"
"sandbox/holger-fetch-worker.rootfs.tar" = ".sandbox-out/holger-fetch-worker.rootfs.tar"
"sandbox/holger-scan-worker.rootfs.tar" = ".sandbox-out/holger-scan-worker.rootfs.tar"
"sandbox/manifest.toml" = ".sandbox-out/manifest.toml"
"sandbox/sigstore-trust.holger.znippy" = ".sandbox-out/sigstore-trust.holger.znippy"

[build.installer.env]
HOLGER_APPLIANCE = "1"
HOLGER_DATA = "/data/holger"
HOLGER_NET = "eth0:dhcp"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"
lands = "release"

[[build.installer.params]]
name = "plugin_trust_root"
label = "Plugin trust root (korp-root-ca, PEM)"
kind = "text"
required = false
staged_file = "korp-root-ca.pem"
lands = "release"

[[build.installer.params]]
name = "intel_trust_policy"
label = "Intel trust policy (holger.intel/v1 signers, RON)"
kind = "text"
required = false
staged_file = "intel-trust.ron"
lands = "release"

[[build.installer.params]]
name = "bundles_trust_policy"
label = "Bundles trust policy (the signers of published bundles, RON)"
kind = "text"
required = false
staged_file = "bundles-trust.ron"
lands = "release"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[[build.installer.params]]
name = "downstream_ca"
label = "The upstream front's CA (PEM) a via: Front downstream verifies it with"
kind = "text"
required = false
staged_file = "downstream-ca.pem"
lands = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[[build.installer]]
name = "holger-downstream-oneway-installer"
variant = "downstream-musl"
volume_id = "HOLGER_DOWNSTREAM_ONEWAY"
target_disk_gib = 64
gpu = false
boot_params = [
    "console=ttyS0",
    "korp.appliance=lean",
    "korp.entry=holger-downstream",
]
cmd = [
    "start",
    "--config",
    "/data/holger.ron",
]
boot-logo = ".nornir/assets/holger-znippy-logo.png"

[build.installer.payload]
kind = "embedded_iso"

[build.installer.payload_entries]
"sandbox/bundle-trust.ron" = ".sandbox-out/bundle-trust.ron"
"sandbox/clamav.rootfs.tar" = ".sandbox-out/clamav.rootfs.tar"
"sandbox/crun" = ".sandbox-out/crun"
"sandbox/heimdall-container-shim" = ".sandbox-out/heimdall-container-shim"
"sandbox/heimdall-guests-0.2.1.intoto.jsonl" = ".sandbox-out/heimdall-guests-0.2.1.intoto.jsonl"
"sandbox/heimdall-verify-bundle-decoder.wasm" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm"
"sandbox/heimdall-verify-bundle-decoder.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.blake3"
"sandbox/heimdall-verify-bundle-decoder.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-decoder.wasm.p7s"
"sandbox/heimdall-verify-bundle-verifier.wasm" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm"
"sandbox/heimdall-verify-bundle-verifier.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.blake3"
"sandbox/heimdall-verify-bundle-verifier.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle-verifier.wasm.p7s"
"sandbox/heimdall-verify-bundle.wasm" = ".sandbox-out/heimdall-verify-bundle.wasm"
"sandbox/heimdall-verify-bundle.wasm.blake3" = ".sandbox-out/heimdall-verify-bundle.wasm.blake3"
"sandbox/heimdall-verify-bundle.wasm.p7s" = ".sandbox-out/heimdall-verify-bundle.wasm.p7s"
"sandbox/holger-scan-worker.rootfs.tar" = ".sandbox-out/holger-scan-worker.rootfs.tar"
"sandbox/manifest.toml" = ".sandbox-out/manifest.toml"
"sandbox/sigstore-trust.holger.znippy" = ".sandbox-out/sigstore-trust.holger.znippy"

[build.installer.env]
HOLGER_DATA = "/data/holger"
HOLGER_NET = "eth0:dhcp"

[build.installer.kernel_donor]
repo = "tunnr"
kernel = "tunnr-kernel"

[build.installer.data]
fs = "xfs"

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = false
boot_param = "korp.site"

[[build.installer.params]]
name = "holger_ron"
label = "Server declaration (holger.ron)"
kind = "text"
required = true
staged_file = "holger.ron"
lands = "release"

[[build.installer.params]]
name = "plugin_trust_root"
label = "Plugin trust root (korp-root-ca, PEM)"
kind = "text"
required = false
staged_file = "korp-root-ca.pem"
lands = "release"

[[build.installer.params]]
name = "intel_trust_policy"
label = "Intel trust policy (holger.intel/v1 signers, RON)"
kind = "text"
required = false
staged_file = "intel-trust.ron"
lands = "release"

[[build.installer.params]]
name = "bundles_trust_policy"
label = "Bundles trust policy (the signers of published bundles, RON)"
kind = "text"
required = false
staged_file = "bundles-trust.ron"
lands = "release"

[[build.installer.params]]
name = "data_disks"
label = "Data disk(s) by device name, comma-separated (e.g. vdb) — everything NOT named here is the boot disk"
kind = "text"
required = false
boot_param = "korp.data.disks"

[[build.installer.params]]
name = "reinstall"
label = "Reinstall policy for a disk that already carries data: keep (upgrade, /data survives — only safe when the identity is NOT re-minted) | wipe (lay it fresh)"
kind = "text"
required = false
boot_param = "korp.reinstall"

[[build.installer.params]]
name = "install_then"
label = "After INSTALL-OK: reboot (a person at the box) | poweroff (a cloud re-image tool detaches the medium)"
kind = "text"
required = false
boot_param = "korp.install.then"

[[build.installer.params]]
name = "live_app"
label = "Live updates of the app: on (default) | off (every new app is a base update)"
kind = "text"
required = false
boot_param = "korp.live_update"

[[build.installer.params]]
name = "holger_net"
label = "The box's network: `eth0:dhcp` or `eth0:<addr>/<prefix>:<gateway>` (static)"
kind = "text"
required = false
staged_file = "holger-net"
lands = "release"

[[build.installer.params]]
name = "trust_policy"
label = "The bundle trust policy (RON) the inbox verifies every bundle with"
kind = "text"
required = true
staged_file = "trust-policy.ron"
lands = "release"

[[build.installer.params]]
name = "upstream_root"
label = "The upstream's attestation root (PEM)"
kind = "text"
required = true
staged_file = "upstream-root.pem"
lands = "release"

[[build.installer.params]]
name = "upstream_signer"
label = "The upstream's evidence signer certificate (PEM)"
kind = "text"
required = true
staged_file = "upstream-signer.pem"
lands = "release"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET"
value = "y"
reason = "the box serves gRPC/HTTP and dials its installer: a kernel with no network stack has no socket to give"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_INET"
value = "y"
reason = "the WireGuard link's outer packets are UDP over IPv4, and CONFIG_TUN depends on INET (drivers/net/Kconfig)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TUN"
value = "y"
reason = "boringtun, the userspace WireGuard of nordisk-pairing (the installer's link and wg0), opens /dev/net/tun — measured missing on the mock 2026-09-28 (ENODEV)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HYPERVISOR_GUEST"
value = "y"
reason = "the gate symbol for every paravirt guest feature; with it off the x86 wall clock falls through to mach_get_cmos_time and the appliance boots on whatever the emulated CMOS was filled with"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT"
value = "y"
reason = "the paravirt op vectors kvmclock installs itself through: x86_platform.get_wallclock and the clocksource"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_KVM_GUEST"
value = "y"
reason = "kvm_get_wallclock: the boot wall clock read from the KVM wall-clock MSR, which the host fills from its own CLOCK_REALTIME - UTC, and out of reach of the hypervisor's -rtc base="

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PARAVIRT_CLOCK"
value = "y"
reason = "the pvclock reader itself (pvclock_read_wallclock), and a monotonic clocksource that survives vCPU migration instead of raw TSC"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI"
value = "y"
reason = "the hot-plug core: a member detached from and re-attached to the RUNNING appliance is otherwise invisible, and UpCloud resizes only detached volumes"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_ACPI"
value = "y"
reason = "acpiphp: the firmware-driven eject path (QEMU i440fx, q35 since 6.1) that acknowledges a detach instead of answering HOTPLUG_FAILED"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCIEPORTBUS"
value = "y"
reason = "binds the PCIe root ports and requests _OSC control, without which native PCIe hot-plug never takes a slot"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_PCIE"
value = "y"
reason = "pciehp: the native PCIe hot-plug path, for q35 with ACPI hot-plug off and for metal"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_HOTPLUG_PCI_SHPC"
value = "y"
reason = "shpchp: a member behind a conventional pci-bridge slot (the cloud's bus topology is unmeasured)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PCI_MSI"
value = "y"
reason = "MEASURED necessary: without MSI `_OSC: not requesting OS control` and pciehp is compiled in but dead"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MULTIUSER"
value = "y"
reason = "the scan sandbox runs every scan as uid 65532 in a user namespace: NAMESPACES and CGROUPS depend on MULTIUSER (lifts the appliance-boot contract's one-user default by name)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NAMESPACES"
value = "y"
reason = "the sandbox is a container: pid, mount, network, uts, ipc and user namespaces"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_USER_NS"
value = "y"
reason = "the worker's uid 65532 maps to an unprivileged host range; host root is never inside (the sandbox's `require_rootless`)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_PID_NS"
value = "y"
reason = "the worker sees only itself; a kill at the deadline reaches every process of it"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_NET_NS"
value = "y"
reason = "`--network none`: a new, empty network namespace, no interface at all"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_UTS_NS"
value = "y"
reason = "its own hostname (holger-scan, holger-clamd)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SYSVIPC"
value = "y"
reason = "IPC_NS depends on SYSVIPC or POSIX_MQUEUE"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_IPC_NS"
value = "y"
reason = "no shared memory or message queue reaches the server from the worker"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUPS"
value = "y"
reason = "the limits: cgroup v2 at /sys/fs/cgroup (memory.max, pids.max, cpu.max)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_MEMCG"
value = "y"
reason = "memory.max and memory.swap.max: the worker's 1 GiB, clamd's 2 GiB, no swap"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_PIDS"
value = "y"
reason = "pids.max: 64 for a scan, 256 for clamd (a fork bomb in an artifact ends there)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CGROUP_SCHED"
value = "y"
reason = "the cpu controller cpu.max hangs off"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_FAIR_GROUP_SCHED"
value = "y"
reason = "the CFS group the cpu quota is accounted on"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_CFS_BANDWIDTH"
value = "y"
reason = "cpu.max: one core for a scan, two for clamd"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP"
value = "y"
reason = "the containers default seccomp profile is applied to every scan (Seccomp: 2 from inside)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_SECCOMP_FILTER"
value = "y"
reason = "the profile is a BPF filter (SECCOMP_SET_MODE_FILTER)"

[[build.installer.requires]]
edge = "kernel"
surface = "kconfig"
symbol = "CONFIG_TMPFS"
value = "y"
reason = "the capped noexec scratch space and clamd's /tmp"

[build.toolchain]
image = "nordisk-cargo-toolchain"
image_sha256 = "86d575e874677da3eb9aff3ba6e38ca600781ee9b7948a9df43ef89a6213c762"
rust_version = "1.97.1"
targets = [
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-linux-musl",
    "wasm32-unknown-unknown",
    "x86_64-unknown-uefi",
]
timeout_secs = 3600
mem_limit_mb = 8192
cpus = 8
siblings = [
    "Skidbladnir",
    "draupnir",
    "edda",
    "facett",
    "funnel-core",
    "modgunn",
    "monetize",
    "skade",
    "tunnr",
    "znippy",
    "znippy-zoomies",
]