Skip to content

Partition model

SpaceOS uses a partition to group services from one project. The partition sets their memory limit, communication rules, and supervisor. Each service still runs in its own virtual machine or container sandbox. Use the same partition names in build.yaml and run.yaml.

build.yaml defines the services and interfaces in a partition. run.yaml assigns memory, CPUs, isolation, and frame routes. SpaceOS starts each service in its selected sandbox.

Configure and inspect a partition

Use the same partition and service names in both manifests. In build.yaml, declare the service and the interfaces it may use:

schema: space.build
version: "1"
kernel: linuxkit/kernel:6.6.13
output: _build/spaceos
partitions:
payload:
services:
- name: classifier
image: ghcr.io/<your-org>/classifier:1
runtime: oci
isolation: runc
interfaces:
- type: frame_bus
apids: [0x120, 0x12F]
send_to: [sdls-downlink]
- name: sdls-downlink
image: ghcr.io/parsimoni-labs/sdls-downlink:1
runtime: oci
isolation: runc
interfaces:
- type: frame_bus
apids: [0x130, 0x13F]

send_to names peer services on the bus. ground is reserved and refused there: frames reach ground through the relay below.

Terminal window
$ space sbom build.yaml | sed -n '1,4p'
SpaceOS Software Bill of Materials
kernel linuxkit/kernel:6.6.13
payload pid1

In run.yaml, assign resources and route the frames. The partition declares no egress list of its own: relay is the one place the flow topology is written, and a manifest that states both is refused.

schema: space.run
version: "1"
image: _build/spaceos
partitions:
payload:
memory: 512
apids: [0x120, 0x12F]
services:
- name: classifier
isolation: runc
cpus: [0, 1]
relay:
from: payload
to: [ground]
ground:
port: 8080
socket: /tmp/spaceos/ground.sock

Build the service image, then rehearse the placement before booting it. The rehearsal names the payload partition, its 512 MB memory limit, the CPU set, and the allowed APID range. A mismatched service name or an unavailable backend fails the rehearsal:

Terminal window
$ chmod +x classifier.sh
$ space build app.yaml -t classifier:dev
Building an app from app.yaml
Built classifier:dev@sha256:e1c0f1a2d51660ac0aeed2d1fd028e656e1b8893d09bb25f96e39c0321003765 (arm64)
Terminal window
$ space run classifier:dev --runtime run.yaml --dry-run
Local target: ...
Boot image: not validated (not in the local store: linuxkit/kernel:6.6.13); build first
image: classifier:dev
partitions:
payload 512 MB apids 0x120, 0x12f
services:
classifier runc cpus 0, 1
relay: payload -> ground (sdls)
ground: port 8080 socket /tmp/spaceos/ground.sock
1 partition, 512 MB total
Dry run complete; no workload started.

Boot image: not validated reports that only the service image is built; a boot also needs the composition that carries the kernel and the partition init. The boot and the report both use the local runner, so this sequence needs the local context. Build it, boot it, then inspect the running partition:

Terminal window
space build . -t classifier:dev
space run classifier:dev --runtime run.yaml
space status --json
space logs classifier

Partitions

A partition is the unit that receives memory and communication rules. Each service in it runs in its own sandbox. The service-level isolation field picks one of three boundaries:

  • A virtual machine. The service is a sealed guest with its own memory and no general-purpose OS inside it. hvt boots a unikernel on the CPU’s virtualization hardware through a Solo5 tender. qemu boots a Unikraft image on a host without that hardware. firecracker boots a unikernel in a micro-VM with a reduced device surface.
  • A confined process. The service runs on the kernel of dom0, the SpaceOS control domain, so a kernel defect crosses this boundary where it does not cross a virtual machine’s. runc runs an OCI container with a read-only root, its own user namespace, a default-deny seccomp profile, and cgroup limits. spt runs a Solo5 unikernel as a seccomp-confined process, for boards without hardware virtualization.
  • A host process. host runs the binary uncontained on a development machine, for test fixtures.

The hypervisor underneath a virtual machine belongs to the target, and you do not name it in isolation. A unikernel built against the Solo5 host interface, about ten calls wide, runs unmodified on any host that implements it, so a change of hypervisor leaves the composition alone. KVM on a Linux host is the substrate a target profile selects today. Xen arrives in the next release [v1.1], and separation kernels are agreed direction [roadmap].

A multi-service partition boots its own init process, the supervisor, which is pid1 by default. The supervisor starts the declared services in dependency order and reports their lifecycle and health. Memory is assigned per partition and CPUs per service in run.yaml; build.yaml declares what the partition contains.

Services in one project may share communication rules while keeping separate sandboxes.

Service interfaces

A service declares typed interfaces at build time; the runner wires them at launch. There are five kinds:

  • Frame bus. Carries fixed-size telemetry and command messages between services and ground. Each message carries an APID, the stream label used to sort messages. The send_to list controls where a service may send it.
  • IP. Provides a standard IP network. The service binds ports on its declared bridges, and connections not listed in the signed release are rejected.
  • Host network. Publishes named TCP ports from the node into the service. It is capability-gated, and a privileged port on a target that permits one changes the container’s own boundary.
  • Data link. Carries large sensor products over a spacecraft serial fabric such as SpaceWire or SpaceFibre, or over a high-bandwidth virtual queue. The declaration names the link, and the signed release decides whether the service may attach to it.
  • Supervision page. A small shared-memory page between the host and the guest carrying heartbeat, mission time, health, and the safe-mode command word. space-runner owns the host side and can put the service in safe mode.

Authorization and APID routing

Each signed release lists what every service may read, write, or open. An APID is the 11-bit CCSDS number used to label a telemetry or command stream. The number helps receivers sort messages. It does not grant permission to send them. Declare the APID range and allowed destinations in run.yaml.

Isolation layers

Partition level. The CPU’s virtualization hardware isolates a virtual machine. A fault, a crash, or a radiation-induced bit flip (a single-event upset) in one partition cannot reach another through memory. Kernel namespaces, cgroups, and seccomp filtering isolate a confined process, a weaker boundary because the service shares the dom0 kernel. The selected execution boundary determines whether the service shares that kernel or runs in a separate virtual machine.

Service level. A multi-service partition’s supervisor keeps its services in separate processes with declared dependencies, healthchecks, and restart policy. Services communicate through their declared interfaces; there is no shared memory between services. The frame bus is sized for telemetry and command messages, so co-located services that need bulk exchange enable the partition block device (disk: true).

Isolation backends

The service-level isolation field selects the concrete backend:

  • hvt: Solo5 on KVM. The unikernel path with hardware VM isolation.
  • spt: Solo5 seccomp tender. The unikernel path where KVM is unavailable.
  • runc: OCI container. Any Linux application, shared dom0 kernel.
  • qemu: QEMU launcher for Unikraft images (x86_64 only).
  • host: host-native process, for development and test fixtures.
  • auto: let the runtime pick a compatible backend.
  • firecracker: KVM-backed micro-VM with a reduced device surface, for unikernels. Linux micro-VM images follow [v1.1].

Flight-domain boundary

The spacecraft’s safety-critical flight software is a separate trust domain and never a SpaceOS partition. It handles attitude control, orbit propagation, and command and data handling, usually on a real-time operating system running a framework such as F-Prime. It boots on its own authority and runs its own fault protection, with a hardware watchdog behind it. SpaceOS observes it over a spacecraft bus and may relay commands that carry its authority. Boot, supervision, and recovery stay with the flight domain, as SpaceOS on the spacecraft describes.

A partition can be bus-facing, meaning it is trusted to exchange telemetry and commands with the flight domain over the frame bus. A bus-facing partition relays; it does not own the flight software.

Hardware acceleration

An accelerator broker opens the GPU, FPGA, or AI engine for a service. Before opening the device, the broker checks the service and device listed in the signed release. A service receives no device access by default.

  • Linux services (isolation: runc) reach accelerators through the device nodes the target profile grants (for example /dev/dri for a GPU).
  • Unikernel services use host-mediated delegation. The guest calls a narrow API and the host forwards it to the device, as Solo5 already does for virtual block and network devices.
  • Direct passthrough, where the guest drives the device itself, requires a dedicated device and an IOMMU, the hardware that limits which memory a device may reach. Targets without both disable passthrough and keep the isolation boundary.

Each accelerator class has its own named delegation interface:

AcceleratorInterfaceExercised on
GPU (NVIDIA)vAccelJetson TX2i
FPGAukAccelXilinx Versal
AI engineVitis AIVCK190
Many-coreOpenCL [roadmap]Kalray MPPA

When services share a GPU, a broker multiplexes the device so that each service sees its own queue.

The target profile lists its accelerators. A service that needs one runs only on a target that lists the matching device.

Manifest references

The two manifests use the same partition names as keys:

build.yaml defines…run.yaml defines…
Supervisor override (optional)How much memory to allocate
What services to bundleWhich CPUs to assign per service
Service interfaces and dependenciesPer-service isolation backend
Per-service healthcheck probeAPID ownership and send_to flow policy
Whether to enable the partition diskRelay shape and ground endpoint

The same composition runs with different placements without rebuilding: 512 MB on a development laptop, or 128 MB on a constrained on-board computer. Board facts such as the kernel, device tree, firmware, and secure-boot keys belong to neither file. They are properties of a connected target.