Document: MEMORANDUM.md
Specification: SOFTCLOUD-NODE-LINUX-1.0
Status: Normative Implementation Baseline
Owner: soft-cloud-dev/os-linux
Primary Consumer: soft-cloud-dev/freebsd-laboratory
Target Hypervisor: FreeBSD bhyve
Target Architecture: amd64
1. Purpose¶
This memorandum defines the normative architecture, build process, boot contract, runtime environment, artifact format, provisioning interface, reproducibility requirements, and acceptance criteria for SoftCloud Node Linux.
SoftCloud Node Linux is a dedicated Linux distribution for Kubernetes nodes executed as bhyve virtual machines.
It is not a customized Ubuntu installation, a generic Debian server image, or an interactive operating-system installation.
The distribution SHALL be produced as a deterministic artifact by soft-cloud-dev/os-linux and consumed by freebsd-laboratory.
2. Normative Language¶
The key words SHALL, SHALL NOT, SHOULD, SHOULD NOT, and MAY are normative.
For this memorandum:
SHALL means the requirement is mandatory.
SHALL NOT means the behavior is prohibited.
SHOULD means the requirement is expected unless a documented technical reason justifies deviation.
SHOULD NOT means the behavior is discouraged unless a documented technical reason justifies it.
MAY means the behavior is optional.
A deployment SHALL NOT claim conformance with this memorandum until all applicable acceptance criteria in Section 24 pass.
3. System Boundary¶
3.1 Artifact Producer¶
os-linux SHALL own:
Linux kernel selection and configuration.
Userspace construction.
systemd.containerd.runc.Kubernetes node binaries.
CNI prerequisite binaries.
The bhyve boot contract.
The machine bootstrap mechanism.
Disk-image construction.
Build provenance.
SBOM generation.
Artifact verification.
Reproducibility validation.
os-linux SHALL produce a machine-independent node artifact.
The primary artifact SHALL be:
softcloud-node-amd64.raw3.2 Laboratory Consumer¶
freebsd-laboratory SHALL own:
FreeBSD host configuration.
bhyvelifecycle.TAP and bridge construction.
VM MAC addresses.
VM UUIDs.
VM hostnames.
VM IP addresses.
seed-image generation.
Kubernetes cluster topology.
kubeadm init.kubeadm join.cluster-level Cilium deployment.
experiments.
runtime observations.
verification evidence.
3.3 Boundary Requirements¶
ARCH-01: Kubernetes cluster state SHALL NOT be embedded in the SoftCloud Node Linux release artifact.
ARCH-02: The same accepted OS image SHALL be usable as either a Kubernetes control-plane node or worker node.
ARCH-03: Machine-specific identity SHALL be supplied or generated after the golden image has been instantiated.
ARCH-04: Cluster-specific identity SHALL be established only by the cluster bootstrap process.
4. Target Platform¶
The initial conforming profile SHALL have the following characteristics:
Architecture amd64
Hypervisor FreeBSD bhyve
Firmware EDK2
Boot format Unified Kernel Image
Kernel Linux LTS
libc glibc
Init systemd
Cgroup hierarchy cgroup v2
Container runtime containerd
OCI runtime runc
Orchestrator Kubernetes
CNI target Cilium
Root filesystem ext4
State filesystem ext4
Network manager systemd-networkd
Console ttyS0
Provisioning softcloud.node/v1PLAT-01: The initial implementation SHALL support amd64.
PLAT-02: The initial implementation SHALL support execution under FreeBSD bhyve.
PLAT-03: Other architectures and hypervisors MAY be added through separate profiles.
PLAT-04: Additional targets SHALL NOT alter the behavior of the kubernetes-node bhyve profile without a memorandum revision.
5. Input and Dependency Model¶
5.1 General Rule¶
Every build input SHALL resolve to an immutable identity before the canonical build begins.
Moving references such as:
latest
stable
current
main
master
6.18.x
1.36.xSHALL NOT constitute accepted build inputs.
5.2 Lockfiles¶
The repository SHALL maintain at least:
locks/
├── sources.lock
├── debian.lock
├── kubernetes.lock
├── containerd.lock
└── toolchain.lockSRC-01: sources.lock SHALL identify Linux and other source archives by exact version and cryptographic digest.
SRC-02: debian.lock SHALL identify the complete Debian package closure used by the root filesystem.
SRC-03: kubernetes.lock SHALL identify exact versions and digests for Kubernetes node binaries and Kubernetes-specific utilities.
SRC-04: containerd.lock SHALL identify exact versions and digests for containerd, runc, and related runtime inputs.
SRC-05: toolchain.lock SHALL identify the canonical compiler, linker, pahole, filesystem tooling, UKI tooling, and other build-critical utilities.
SRC-06: Lockfile changes SHALL be reviewable independently from build logic changes.
6. Fetch and Build Separation¶
The build process SHALL contain an explicit trust boundary:
FETCH
↓
VERIFY
↓
VERIFIED LOCAL INPUT SET
↓
DISABLE NETWORK
↓
BUILD
↓
VERIFY OUTPUTBUILD-01: All network-dependent inputs SHALL be retrieved before the canonical build phase.
BUILD-02: Every retrieved input SHALL be cryptographically verified before entering the build input set.
BUILD-03: The canonical image build SHALL succeed with network access disabled.
BUILD-04: The build SHALL fail when a required undeclared input is unavailable locally.
BUILD-05: The build SHALL NOT silently retrieve dependencies during compilation, package assembly, UKI creation, filesystem construction, or image generation.
7. Canonical Builder¶
Linux kernel and Linux userspace construction SHALL occur in a versioned canonical Linux build environment.
FreeBSD SHALL remain responsible for final bhyve execution validation.
verified inputs
|
v
canonical Linux builder
|
+--> kernel
+--> rootfs
+--> UKI
+--> disk image
|
v
digested artifacts
|
v
FreeBSD bhyve verificationBLD-01: The canonical builder definition SHALL be version controlled.
BLD-02: The canonical builder SHALL have a deterministic dependency set.
BLD-03: Compiler and linker versions SHALL be recorded in provenance.
BLD-04: The pahole version SHALL be recorded in provenance.
BLD-05: Filesystem-generation tools SHALL be recorded in provenance.
BLD-06: UKI-generation tooling SHALL be recorded in provenance.
8. Linux Kernel¶
A dedicated Kubernetes/bhyve configuration SHALL exist at:
kernel/config/linux-kubernetes-bhyve.configThe generic bhyve kernel configuration SHALL NOT silently become the Kubernetes profile.
8.1 Root Boot Requirements¶
The following capabilities SHALL be built directly into the kernel:
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BLK=y
CONFIG_EXT4_FS=yThese requirements SHALL NOT be satisfied by modules.
8.2 Namespaces and Cgroups¶
The Kubernetes profile SHALL provide at least:
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_BPF=y8.3 eBPF and Cilium¶
The profile SHALL provide at least:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_SCH_FQ=y
CONFIG_NET_ACT_BPF=y
CONFIG_LWTUNNEL=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_VXLAN=y
CONFIG_GENEVE=y8.4 Networking¶
The profile SHALL provide bridge, routing, conntrack, Netfilter, nftables, TPROXY, VETH, and policy-routing facilities required by Kubernetes and the selected Cilium configuration.
At minimum:
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_TABLES=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_VETH=y
CONFIG_BRIDGE=y
CONFIG_BRIDGE_NETFILTER=y8.5 Storage and Security¶
The profile SHALL provide at least:
CONFIG_OVERLAY_FS=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y8.6 Swap¶
The dedicated Kubernetes-node profile SHOULD compile with:
CONFIG_SWAP=nIf swap support is retained for another reason, swap SHALL remain disabled for the complete lifetime of a conforming Kubernetes node unless a future Kubernetes profile explicitly defines otherwise.
8.7 Security Mitigations¶
CPU security mitigations SHALL remain enabled by default.
A laboratory-specific profile MAY disable individual mitigations only when:
the behavior under study requires it;
the change is explicit;
the change is documented;
the resulting artifact is distinguishable from the normal Kubernetes-node artifact.
9. BTF Contract¶
The kernel SHALL provide valid BTF suitable for the selected Cilium release.
Configuration alone SHALL NOT satisfy this requirement.
BTF-01: CONFIG_DEBUG_INFO_BTF=y SHALL be enabled.
BTF-02: The canonical builder SHALL contain a pinned compatible pahole.
BTF-03: The resulting vmlinux SHALL contain a valid .BTF section.
BTF-04: BTF data SHALL be parsed during validation.
A validation equivalent to:
bpftool btf dump file build/vmlinux format raw >/dev/nullSHALL succeed.
BTF-05: Failure to generate or parse BTF SHALL reject the kernel before disk-image construction.
10. Boot Contract¶
10.1 Unified Kernel Image¶
A Unified Kernel Image is mandatory in the initial implementation.
The canonical boot path SHALL be:
bhyve
↓
EDK2
↓
EFI System Partition
↓
/EFI/BOOT/BOOTX64.EFI
↓
UKI
↓
Linux
↓
systemdBOOT-01: /EFI/BOOT/BOOTX64.EFI SHALL be a self-contained accepted boot artifact.
BOOT-02: Normal boot SHALL NOT require persistent UEFI NVRAM variables.
BOOT-03: The system SHALL boot with a fresh or stateless EDK2 variable store.
10.2 Kernel Command Line¶
The UKI SHALL contain the required kernel command line.
At minimum it SHALL encode equivalent semantics to:
root=PARTUUID=<ROOT_PARTUUID>
rootfstype=ext4
rootwait
console=ttyS0,115200
cgroup_no_v1=allAdditional options MAY be included when defined by the profile.
BOOT-04: rootwait SHALL be present.
BOOT-05: The root filesystem SHALL be identified deterministically.
BOOT-06: The root device SHALL NOT depend on incidental /dev/vdX enumeration.
10.3 Deterministic UKI¶
BOOT-07: The UKI binary SHALL be generated deterministically.
All PE/COFF fields whose values may depend on wall-clock build time, including the PE/COFF header timestamp, SHALL be derived from or normalized against SOURCE_DATE_EPOCH.
Two otherwise identical builds SHALL NOT produce different UKI binaries solely because they were executed at different wall-clock times.
UKI reproducibility SHALL be verified by digest comparison as part of R2 and higher reproducibility testing.
10.4 Initramfs¶
The image MAY include a minimal initramfs.
The initramfs SHALL NOT be required to provide basic VirtIO block or ext4 support.
11. Userspace¶
SoftCloud Node Linux SHALL use a glibc userspace.
Debian packages MAY serve as upstream userspace inputs.
The resulting OS identity SHALL remain SoftCloud Node Linux.
11.1 Debian Snapshot¶
USR-01: Debian packages SHALL come from a timestamped archive or equivalent immutable source.
USR-02: The build SHALL NOT consume a moving Debian stable mirror as an accepted source.
USR-03: The exact snapshot identity SHALL be recorded in the artifact manifest.
11.2 Rootfs Assembly¶
mmdebstrap SHOULD be used as the rootfs construction mechanism in the canonical builder.
The rootfs pipeline SHALL be equivalent to:
locked snapshot
↓
locked package closure
↓
rootfs staging tree
↓
SoftCloud overlay
↓
ldconfig
↓
normalization
↓
filesystem generationUSR-04: Package maintainer scripts SHALL be controlled to prevent host-dependent or nondeterministic artifact mutations.
USR-05: Dynamic user/group allocation during the canonical build SHALL be deterministic.
USR-06: The rootfs build SHALL execute:
ldconfig -r <target-root>or an equivalent deterministic operation before final filesystem generation.
USR-07: First boot SHALL NOT be required merely to make normal dynamically linked utilities executable.
12. Operating-System Identity¶
The release artifact SHALL identify itself as SoftCloud Node Linux.
At minimum:
/etc/os-releaseSHALL provide the distribution identity.
The image SHOULD also provide:
/etc/issuefor human-readable console identification.
ID-01: The artifact SHALL NOT identify itself primarily as Ubuntu or Debian.
ID-02: Upstream origin metadata MAY identify Debian as a userspace source.
13. Container and Kubernetes Runtime¶
The accepted image SHALL contain:
containerd
runc
kubelet
kubeadm
kubectl
cri-toolsThe image SHALL also contain required reference CNI lifecycle binaries, including:
/opt/cni/bin/loopback13.1 Runtime Rules¶
RUN-01: containerd SHALL expose a functioning CRI endpoint.
RUN-02: containerd SHALL use the systemd cgroup driver.
RUN-03: kubelet SHALL use the systemd cgroup driver.
RUN-04: The node SHALL use cgroup v2.
RUN-05: cgroup v1 controllers SHALL NOT be required for the Kubernetes-node profile.
RUN-06: /opt/cni/bin/loopback SHALL exist before Kubernetes bootstrap.
RUN-07: The Kubernetes node BPF filesystem SHALL be mounted at:
/sys/fs/bpfin the node’s host mount namespace and SHALL have shared mount-propagation semantics before containerd and kubelet start.
The distribution SHOULD provide an explicit systemd-managed boot unit sequence equivalent to:
mount bpffs at /sys/fs/bpf
↓
make /sys/fs/bpf shared
↓
containerd
↓
kubeletThe implementation SHALL NOT depend on Cilium performing the first persistent bpffs mount after Kubernetes startup.
The runtime verifier SHALL confirm both:
filesystem type = bpf
mount propagation = sharedbefore the node is accepted.
13.2 Cluster-State Boundary¶
The image SHALL NOT contain:
kubeadm join tokens
cluster CA private keys
node certificates
etcd data
preconfigured cluster membership
Cilium cluster identityCluster state SHALL be created by freebsd-laboratory or the cluster bootstrap workflow.
14. Disk Layout¶
The image SHALL use GPT.
The logical layout SHALL be:
+---------------------------------------------------------+
| GPT |
+---------------+----------------------+------------------+
| p1 ESP | p2 OS root | p3 node-state |
| FAT32 | ext4 | dynamic ext4 |
+---------------+----------------------+------------------+14.1 EFI System Partition¶
p1 SHALL contain the UKI.
The standard fallback boot path SHALL be:
/EFI/BOOT/BOOTX64.EFI14.2 Root Partition¶
p2 SHALL contain the distribution root filesystem.
Its partition identity SHALL be deterministic.
Its filesystem UUID SHALL be deterministic.
LAYOUT-01: For SoftCloud Node Linux v1, p2 SHALL be mounted read-write during normal operation.
Runtime mutability of p2 SHALL NOT redefine the release artifact.
Workload and node-state directories identified by this memorandum SHALL be delegated to p3.
A future read-only or verified-root profile MAY supersede this behavior only through an explicit profile or memorandum revision.
14.3 State Partition¶
p3 SHALL represent mutable node state.
The release process SHALL NOT assume a fixed final bhyve disk size.
The state filesystem SHALL be initialized or expanded according to the actual VM disk size.
Mutable state SHALL include at least:
/var/lib/containerd
/var/lib/kubelet
/var/lib/etcd
/var/logLAYOUT-02: Projection of mutable state from p3 into standard filesystem locations SHALL use systemd-managed bind mounts.
Symbolic links SHALL NOT be used as the state-projection mechanism.
The bind-mount definition and its required propagation semantics SHALL be explicit and version controlled.
Where recursive propagation is required by a consumer, the implementation SHALL apply rshared semantics; where non-recursive propagation is sufficient, the implementation SHALL explicitly declare the selected shared propagation mode.
A conforming implementation SHALL establish the bind mount before services consuming the corresponding state path start.
Conceptually:
p3: node-state
│
├── containerd/
├── kubelet/
├── etcd/
└── log/
│
├── bind → /var/lib/containerd
├── bind → /var/lib/kubelet
├── bind → /var/lib/etcd
└── bind → /var/log15. First-Boot State Provisioning¶
systemd-repart SHOULD provide first-boot partition-growth and filesystem-initialization behavior.
A configuration equivalent to:
[Partition]
Type=linux-generic
Label=node-state
Format=ext4
MountPoint=/var/mnt/state
GrowFileSystem=yesSHALL be maintained.
STATE-01: A cloned release image SHALL support different final virtual-disk capacities.
STATE-02: Node state SHALL expand without requiring bespoke interactive partitioning.
STATE-03: Node state SHALL remain logically separate from the replaceable OS partition.
STATE-04: The mechanism SHALL work for both control-plane and worker nodes.
STATE-05: The state filesystem SHALL be mounted before state bind mounts are activated.
STATE-06: Services consuming /var/lib/containerd, /var/lib/kubelet, /var/lib/etcd, or /var/log SHALL be ordered after their corresponding state mounts.
16. Machine Bootstrap Contract¶
The distribution SHALL implement:
softcloud.node/v1This contract replaces cloud-init for the dedicated bhyve profile.
A seed MAY contain information equivalent to:
schema: softcloud.node/v1
identity:
hostname: k8s-w1
network:
interface: eth0
address: 192.168.70.12/24
gateway: 192.168.70.1
dns:
- 192.168.70.1
ssh:
authorized_keys:
- ssh-ed25519 ...
class:
name: kubernetes-node16.1 Allowed Responsibilities¶
softcloud-seed SHALL be permitted to configure:
hostname;
network configuration;
SSH authorized keys;
machine-local identity;
profile-approved machine-local configuration.
16.2 Forbidden Responsibilities¶
The seed SHALL NOT contain or directly establish:
Kubernetes cluster membership;
reusable
kubeadmtokens;Kubernetes private CA keys;
etcd state;
container runtime workload state;
a shared static machine ID.
17. Seed Service Ordering¶
softcloud-seed SHALL use systemd device activation rather than systemd-udev-settle.service.
The dependency graph SHALL include:
[Unit]
Description=SoftCloud Seed Initializer
DefaultDependencies=no
Requires=dev-disk-by\x2dlabel-CIDATA.device
After=dev-disk-by\x2dlabel-CIDATA.device local-fs.target
Before=sysinit.target systemd-networkd.service sshd.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/softcloud/softcloud-seed --mount /dev/disk/by-label/CIDATA
StandardOutput=journal+console
[Install]
WantedBy=sysinit.targetWhere required to write the persistent initialization marker, the implementation SHALL additionally establish an explicit dependency on the mounted node-state filesystem.
The exact dependency graph MAY contain additional required units, but SHALL preserve the following invariants.
SEED-01: Seed schema validation SHALL finish before seed data is applied.
SEED-02: Network configuration SHALL be written before systemd-networkd configures the node interface.
SEED-03: SSH authorized keys SHALL be installed before the SSH daemon accepts connections.
SEED-04: Invalid seed data SHALL fail closed.
SEED-05: Seed processing SHALL emit diagnostic information to the journal and serial console.
SEED-06: Seed processing SHALL be safe against unintended repeated application.
SEED-07: Upon successful first-time configuration, softcloud-seed SHALL create a persistent initialization marker on the node-state filesystem.
The marker SHALL prevent normal seed initialization from executing again on subsequent boots when the original CIDATA volume remains attached.
The marker SHOULD contain at least:
softcloud.node schema version
seed digest
initialization completion stateA suitable location is:
/var/mnt/state/.softcloud/seed-initializedor an equivalent path owned by the SoftCloud bootstrap subsystem.
If an attached seed differs from the seed digest recorded by the initialization marker, the bootstrap implementation SHALL NOT silently reconfigure the machine.
It SHALL either:
fail with a diagnostic indicating seed identity mismatch; or
require an explicit reset/reprovisioning operation defined by the implementation.
CIDATA presence alone SHALL NOT cause repeated initialization.
18. Machine Identity¶
The golden image SHALL contain no shared active machine identity.
MID-01: /etc/machine-id SHALL be empty or in a documented systemd uninitialized state in the release artifact.
MID-02: First boot SHALL generate or establish a unique machine ID.
MID-03: VM clones SHALL receive different machine IDs.
MID-04: Persistent SSH host identity SHALL NOT be duplicated across cloned machines.
MID-05: VM-specific UUIDs SHALL be supplied by the virtualization environment.
For a three-node laboratory:
machine-id(cp1) != machine-id(w1)
machine-id(cp1) != machine-id(w2)
machine-id(w1) != machine-id(w2)SHALL hold.
19. Deterministic Filesystem Construction¶
19.1 Root Tree Normalization¶
Before filesystem generation:
DET-01: File ownership SHALL be normalized.
DET-02: File and directory ordering SHALL be deterministic.
DET-03: Relevant timestamps SHALL be clamped to SOURCE_DATE_EPOCH.
A normalization mechanism equivalent to:
find rootfs \
-exec touch --no-dereference \
--date="@${SOURCE_DATE_EPOCH}" {} +MAY be used.
19.2 ext4¶
Filesystem generation SHALL control nondeterministic values.
An operation equivalent to:
mke2fs \
-d rootfs/ \
-t ext4 \
-O ^has_journal,dir_index \
-U "${ROOT_UUID}" \
-E nodiscard,lazy_itable_init=0,lazy_journal_init=0 \
root.imgMAY be used.
DET-04: Root filesystem UUIDs SHALL NOT come from runtime randomness.
DET-05: Lazy inode-table initialization SHALL NOT introduce post-build differences into an artifact declared reproducible.
DET-06: Filesystem creation parameters SHALL be recorded or derivable from version-controlled configuration.
19.3 GPT¶
The image builder SHALL explicitly control:
disk GUID
partition GUIDs
partition type GUIDs
partition start LBAs
partition sizes
alignmentDET-07: Partition GUIDs SHALL NOT be generated randomly during an accepted build.
DET-08: Partition placement SHALL use explicit deterministic alignment.
The default SHOULD use 1 MiB alignment.
20. Reproducibility Levels¶
The project SHALL classify reproducibility using:
R0 identical resolved dependency closure
R1 identical normalized rootfs manifest
R2 identical kernel and UKI digests
R3 identical filesystem images
R4 identical complete raw disk imageREP-01: Every release SHALL declare its achieved reproducibility level.
REP-02: R4 SHALL be the target for a fully accepted SoftCloud Node Linux release.
REP-03: An R4 claim SHALL require two independent clean builds producing identical cryptographic digests for the complete raw image.
REP-04: R2 and higher SHALL require bit-identical UKI output, including deterministic PE/COFF metadata required by BOOT-07.
Conceptually:
clean build environment A
↓
image A
↓
SHA-A
clean build environment B
↓
image B
↓
SHA-B
SHA-A == SHA-B21. Release Artifacts¶
A release SHALL produce at least:
artifacts/<release>/
├── softcloud-node-amd64.raw
├── BOOTX64.EFI
├── kernel.config
├── artifact-manifest.json
├── sbom.spdx.json
├── provenance.json
└── SHA256SUMSA normalized rootfs archive MAY additionally be published:
rootfs.tar.zst21.1 Artifact Manifest¶
artifact-manifest.json SHALL contain or reference:
schema version;
distribution identity;
release identity;
architecture;
profile;
Linux version;
Linux source digest;
kernel configuration digest;
vmlinuxdigest;UKI digest;
root filesystem digest;
disk image digest;
Debian snapshot identity;
Debian package-lock digest;
Kubernetes version;
containerd version;
runc version;
toolchain-lock digest;
builder identity;
SOURCE_DATE_EPOCH;source repository revision;
acceptance-test results;
achieved reproducibility level.
The manifest SHALL validate against:
softcloud.artifact/v1or its explicitly versioned successor.
22. SBOM and Provenance¶
SUP-01: Every accepted release SHALL contain an SBOM.
SUP-02: SPDX JSON SHOULD be the canonical initial SBOM representation.
SUP-03: Every accepted release SHALL contain build provenance.
SUP-04: Provenance SHALL identify the repository revision used to build the artifact.
SUP-05: Provenance SHALL identify the canonical builder.
SUP-06: Provenance SHALL identify all lockfile digests.
SUP-07: An artifact whose provenance cannot be associated with its source inputs SHALL NOT be accepted.
23. Repository Layout¶
The repository SHOULD converge on:
os-linux/
├── MEMORANDUM.md
├── README.md
├── os.yaml
│
├── schemas/
│ ├── softcloud.os.v1.schema.json
│ ├── softcloud.artifact.v1.schema.json
│ └── softcloud.node.v1.schema.json
│
├── locks/
│ ├── sources.lock
│ ├── debian.lock
│ ├── kubernetes.lock
│ ├── containerd.lock
│ └── toolchain.lock
│
├── builder/
│ └── profile.yaml
│
├── kernel/
│ ├── config/
│ │ ├── linux-bhyve.config
│ │ └── linux-kubernetes-bhyve.config
│ ├── patches/
│ └── build.sh
│
├── userspace/
│ ├── debian/
│ │ ├── packages.in
│ │ ├── packages.lock
│ │ └── build-rootfs.sh
│ └── overlay/
│
├── boot/
│ ├── cmdline.txt
│ ├── build-uki.sh
│ └── os-release
│
├── profiles/
│ └── kubernetes-node/
│ ├── profile.yaml
│ ├── sysctl.conf
│ ├── containerd.toml
│ ├── repart.d/
│ └── systemd/
│
├── seed/
│ ├── softcloud-seed
│ ├── softcloud-seed.service
│ └── schema/
│
├── runtime/
│ └── bhyve/
│ ├── build-image.sh
│ ├── make-seed.sh
│ └── boot-test.sh
│
├── tools/
│ ├── resolve-sources.py
│ ├── validate-locks.py
│ ├── normalize-rootfs.py
│ ├── make-manifest.py
│ └── make-sbom.py
│
├── tests/
│ ├── kernel/
│ ├── rootfs/
│ ├── boot/
│ ├── seed/
│ ├── kubernetes/
│ └── reproducibility/
│
└── artifacts/Equivalent organization MAY be used where repository evolution requires it, provided the ownership boundaries defined by this memorandum remain explicit.
24. Acceptance Criteria¶
SN-01 — Verified Inputs¶
Every network-retrieved build input SHALL have a cryptographic identity and SHALL be verified before use.
SN-02 — No Moving Inputs¶
No moving latest, stable, current, branch-tip, or equivalent reference SHALL participate in an accepted build without first resolving to an immutable locked identity.
SN-03 — Kernel Source¶
The kernel source SHALL match sources.lock.
SN-04 — Boot Configuration¶
The kernel and UKI SHALL satisfy the bhyve boot contract. The machine SHALL boot without unmanaged persistent UEFI NVRAM kernel arguments.
SN-05 — Cilium/BTF¶
The kernel SHALL satisfy the selected Kubernetes/Cilium requirements. Generated BTF SHALL successfully parse with bpftool or an equivalent validator.
SN-06 — CPU Mitigations¶
CPU security mitigations SHALL remain enabled for the normal profile unless explicitly waived by a distinct experimental profile.
SN-07 — Package Closure¶
Every package contained in the root filesystem SHALL be represented by an accepted package or artifact lock.
SN-08 — OS Identity¶
/etc/os-release SHALL identify the system as SoftCloud Node Linux.
SN-09 — Init¶
PID 1 SHALL be systemd.
SN-10 — cgroup v2¶
The running node SHALL use the cgroup v2 hierarchy required by the profile.
SN-11 — CRI¶
The containerd CRI endpoint SHALL respond successfully.
SN-12 — systemd Cgroups¶
containerd and kubelet SHALL use compatible systemd cgroup management.
SN-13 — Swap¶
Swap SHALL be unavailable or disabled according to the Kubernetes-node profile.
SN-14 — IP Forwarding¶
Required Linux forwarding settings SHALL be active.
SN-15 — Machine Identity¶
The release artifact SHALL contain no shared active machine identity. Three independently instantiated laboratory nodes SHALL have distinct machine IDs.
SN-16 — bhyve Boot¶
The UKI SHALL boot directly under bhyve/EDK2 without requiring persistent boot-entry configuration.
SN-17 — VirtIO Block¶
The root disk SHALL operate through the selected bhyve VirtIO block interface.
SN-18 — VirtIO Network¶
The network interface SHALL operate through the selected bhyve VirtIO network interface.
SN-19 — Serial Console¶
The kernel and userspace SHALL expose a functioning serial console through ttyS0.
SN-20 — Seed Validation¶
Seed data SHALL validate against softcloud.node/v1 before configuration is applied. Invalid input SHALL fail closed.
SN-21 — SSH Authentication¶
A fresh node SHALL accept SSH only according to the profile’s approved authentication policy. Seed-provided public keys SHALL be supported. Password-based remote root authentication SHALL NOT be enabled by default.
SN-22 — kubeadm Preflight¶
kubeadm preflight SHALL succeed on a clean node. /opt/cni/bin/loopback SHALL exist.
SN-23 — Kubernetes Join¶
A worker instantiated from the accepted image SHALL successfully join the target Kubernetes cluster.
SN-24 — Cilium Health¶
Cilium SHALL report healthy after deployment.
SN-25 — Pod Connectivity¶
Cross-node Pod communication SHALL pass the laboratory connectivity test.
SN-26 — Service Connectivity¶
ClusterIP Service routing SHALL function.
SN-27 — DNS¶
CoreDNS resolution SHALL function for Kubernetes service names.
SN-28 — SBOM¶
The accepted release SHALL include an SBOM.
SN-29 — Artifact Contract¶
artifact-manifest.json SHALL validate against the selected softcloud.artifact schema.
SN-30 — Reproducibility¶
An independent clean rebuild SHALL meet the release’s declared reproducibility level.
SN-31 — Build Self-Containment¶
After the fetch-and-verify phase, the canonical builder SHALL successfully build with external network access disabled.
SN-32 — Deterministic UKI¶
Two clean builds with identical locked inputs and identical SOURCE_DATE_EPOCH SHALL produce identical BOOTX64.EFI digests. PE/COFF build timestamps SHALL NOT vary with wall-clock build time.
SN-33 — bpffs Propagation¶
Before containerd and kubelet start:
/sys/fs/bpfSHALL be mounted asbpf;the mount SHALL have shared propagation semantics.
SN-34 — State Projection¶
A booted node SHALL demonstrate that mutable node-state paths are bind-mounted from p3. The verifier SHALL confirm that these paths are mount points rather than symbolic links. At minimum: /var/lib/containerd, /var/lib/kubelet, /var/lib/etcd, and /var/log SHALL comply.
SN-35 — Seed One-Shot Semantics¶
After first successful initialization:
an initialization marker SHALL exist on
p3;rebooting with the same
CIDATAattached SHALL NOT reapply seed configuration;a changed seed SHALL NOT be silently applied over an existing initialization marker.
25. Integration Test Topology¶
The primary laboratory acceptance topology SHALL use three machines instantiated from the same OS artifact:
softcloud-node-amd64.raw
|
identical artifact digest
|
+-------------+-------------+
| | |
v v v
k8s-cp1 k8s-w1 k8s-w2
| | |
seed A seed B seed C
| | |
+-------------+-------------+
|
Kubernetes
|
CiliumThe OS artifact digest SHALL be identical for all three nodes before machine-local state is initialized.
26. Initial Network Contract¶
The first freebsd-laboratory integration MAY use:
Node network: 192.168.70.0/24
Pod network: 10.244.0.0/16
Service network: 10.96.0.0/12
Cluster domain: cluster.localThese values belong to laboratory topology and cluster configuration.
They SHALL NOT become hard dependencies of the generic SoftCloud Node Linux artifact.
27. Initial Implementation Baseline¶
The first implementation is intended to use:
Linux family: 6.18 LTS
Userspace source: Debian 13
Init: systemd
Runtime: containerd + runc
Kubernetes family: 1.36
CNI: Cilium
Filesystem: ext4
Firmware: EDK2Exact patch versions and source identities SHALL reside in lockfiles.
If a value in this section conflicts with a lockfile used for an accepted build, one of the following SHALL occur before release:
this memorandum is revised; or
the implementation is brought back into conformity.
Unreviewed divergence SHALL NOT be accepted.
28. Implementation Sequence¶
Implementation SHOULD proceed in the following dependency order.
Phase 1 — Specification and Builder¶
Freeze this memorandum.
Define
softcloud.node/v1.Define the canonical Linux builder.
Create
toolchain.lock.Remove existing source/version inconsistencies.
Phase 2 — Kernel and UKI¶
Lock Linux source.
Create
linux-kubernetes-bhyve.config.Integrate BTF generation.
Verify BTF using
bpftool.Create the UKI.
Embed the deterministic root reference.
Verify
rootwait.Normalize PE/COFF timestamps from
SOURCE_DATE_EPOCH.Demonstrate stateless EDK2 boot.
Demonstrate bit-identical UKI rebuild.
Phase 3 — Root Filesystem¶
Lock the Debian snapshot.
Resolve the complete package closure.
Build with
mmdebstrap.Apply the SoftCloud overlay.
Execute
ldconfig.Install locked runtime binaries.
Install locked Kubernetes binaries.
Install CNI loopback.
Configure bpffs boot mounting.
Configure shared bpffs propagation.
Normalize the filesystem tree.
Phase 4 — Deterministic Image¶
Generate deterministic GPT.
Generate deterministic ESP.
Generate deterministic root ext4.
Define expandable state storage.
Integrate
systemd-repart.Create systemd bind mount units.
Define mount propagation semantics.
Generate the artifact manifest.
Phase 5 — Machine Bootstrap¶
Implement
softcloud-seed.Implement schema validation.
Implement direct CIDATA device-unit activation.
Initialize machine identity.
Configure networking.
Configure hostname.
Configure SSH authorization.
Write persistent first-boot marker.
Verify changed-seed rejection semantics.
Phase 6 — bhyve Verification¶
Boot from the UKI.
Verify serial console.
Verify VirtIO block.
Verify VirtIO networking.
Verify systemd.
Verify cgroup v2.
Verify state expansion.
Verify state bind mounts.
Verify bpffs and mount propagation.
Verify seed one-shot behavior.
Phase 7 — Kubernetes Verification¶
Verify CRI.
Run
kubeadmpreflight.Initialize
k8s-cp1.Join
k8s-w1.Join
k8s-w2.Deploy Cilium.
Verify Pod networking.
Verify Services.
Verify DNS.
Phase 8 — Supply Chain and Release¶
Perform network-disabled build.
Generate SBOM.
Generate provenance.
Generate artifact manifest.
Perform an independent clean rebuild.
Determine R0-R4 reproducibility level.
Publish only after all applicable SN acceptance gates pass.
29. Upgrade Model¶
SoftCloud Node Linux SHALL prefer artifact replacement over in-place mutation.
The intended lifecycle is:
lock update
↓
new build
↓
verification
↓
new artifact
↓
node replacement or controlled reprovisioningRoutine administration SHOULD NOT use:
SSH
↓
apt upgrade
↓
manual package replacement
↓
continued use of mutated nodeUPG-01: Security or Kubernetes updates SHOULD result in a new OS artifact.
UPG-02: Manual modification of an instantiated node SHALL NOT alter the definition of the accepted release artifact.
UPG-03: Nodes modified interactively MAY be used for experiments but SHALL NOT be treated as pristine conformance instances.
UPG-04: The fact that p2 is mounted read-write in v1 SHALL NOT authorize routine in-place OS package upgrades as the normal lifecycle mechanism.
30. Non-Goals¶
The initial release SHALL NOT attempt to provide:
a general-purpose desktop environment;
a conventional interactive OS installer;
arbitrary package-management workflows on production nodes;
automatic Kubernetes cluster creation inside the image;
cloud-provider-specific initialization;
multi-distribution compatibility;
arbitrary hypervisor compatibility;
persistent machine identity in the golden image;
general-purpose
cloud-initcompatibility;in-place mutable release upgrades.
Such capabilities MAY be introduced by future profiles or memorandum revisions.
31. Change Control¶
Changes are divided into three classes.
31.1 Architectural Changes¶
An architectural change modifies one or more of:
artifact ownership
trust boundaries
boot model
identity model
storage model
provisioning contract
cluster/OS boundary
reproducibility model
supported execution model
Architectural changes SHALL require revision of this memorandum.
31.2 Baseline Changes¶
A baseline change includes:
Linux patch version
Kubernetes patch version
containerd version
runc version
Debian snapshot timestamp
toolchain version
package closure
Baseline changes SHALL update the relevant lockfiles and SHALL rerun all applicable acceptance criteria. A memorandum revision is required when the new baseline invalidates a normative architectural requirement.
31.3 Implementation Changes¶
Implementation-only changes MAY occur without a memorandum revision when they preserve all normative behavior and contracts. Examples include internal script refactoring, test implementation improvements, build performance improvements, error message improvements, and non-semantic repository reorganization.
32. Completion Condition¶
SoftCloud Node Linux 1.0 SHALL be considered implemented when:
one locked OS definition
↓
one network-isolated canonical build
↓
one deterministic UKI
↓
one reproducible bhyve raw image
↓
three independently instantiated machines
↓
three unique machine identities
↓
persistent node-state bind mounts
↓
shared node bpffs
↓
one-shot seed initialization
↓
one kubeadm Kubernetes cluster
↓
healthy Cilium
↓
successful Pod / Service / DNS tests
↓
SBOM + provenance + artifact manifest
↓
all applicable SN-01 through SN-35 PASSThe architectural invariant is:
The machine changes; the operating-system artifact does not.