Skip to content

CosmoOS 1.0.11

Choose a tag to compare

@github-actions github-actions released this 23 Oct 13:46
· 40 commits to main since this release
af38131

CosmoOS 1.0.11

Mirrors that survive a disk

The installer can put the root on two disks.

cosmo$ cosmo-install vdc --mirror vdd
...
cosmo-install: the root is mirrored on vdc2 and vdd2 (vdd's root partition, partuuid ...)

Both disks get the same layout and their own EFI System Partition, so
either can boot. The root is one pool kept as two copies.

When a disk fails or is pulled, the system keeps running.

  • The kernel says so once:

    pool: cosmo-root: member 0 copy 1 (vda2) MISSING (-19): the member is degraded
    
  • /proc/mounts shows rw,degraded.

  • cosmo-pool status says DEGRADED and how much the missing copy
    missed.

  • A boot with a copy missing still boots, and init says so.

  • I/O that no copy can satisfy fails with EIO; it is not a panic.

cosmo-pool replaces a disk, and a spare takes over by itself.

  • cosmo-pool replace 0:1 vdb puts a new disk in a missing copy's
    place.
  • The new copy is resilvered while the system runs. Every block the
    pool uses is copied to it at most fs.resilver_rate blocks a second
    (8192, 32 MiB/s, unless set). Every write goes to it meanwhile, and a
    reboot resumes where the resilver stopped.
  • A disk that was pulled and comes back while the pool stays mounted is
    caught up from the pool's record of what it missed, rather than
    rebuilt. One that was missing when the pool was mounted is rebuilt
    whole.
  • The other subcommands: status, offline, online, attach (make a
    single disk a mirror), detach, add-spare and remove-spare.
  • A spare takes the place of a copy that fails or whose disk goes, with
    no command.
  • A copy that fails more than fs.fault_errors times (16) is taken out
    as FAULTED.

Disks can be pulled and added while the system runs. PCIe native
hotplug works on both architectures: removal through the slot's
attention button, and insertion with the disk's partitions read. This
covers virtio-blk and NVMe behind PCIe root ports.

See the guide's new page, Mirrors.

Fixes

  • Every copy of a mounted mirror counts as in use. /dev/blkctl
    and mkfs refuse a device that another copy of a mounted pool
    stands on, not just the device the pool was mounted from.
  • Devices behind a PCIe root port get their DMA mapping. This
    applies to VT-d's bridge scopes and to SMMUv3 stream ids above 255.

The pool's format

A pool is raised to format 13 the first time it has a copy to record,
which is when a mirror is degraded. Releases up to v1.0.10 cannot
mount a pool at format 13. A pool that is never degraded keeps its
format.

Upgrading from v1.0.10

cosmo-upgrade --fetch v1.0.11, reboot, then pkg update && pkg upgrade. The upgrade takes a boot environment, so cosmo-upgrade --rollback returns the root and the boot set as they were. A root pool
that has been degraded under 1.0.11 is at format 13, and the rolled-back
1.0.10 kernel cannot mount it.

cosmo-upgrade writes the new release to the ESP of the disk the
system booted from only. On a mirrored root, the other disk's ESP keeps
the release it was installed with.

Tested:

  • On every change, on both architectures, beside the release tests:
    • make test-mirror: install onto two disks; pull one under a writer;
      replace and resilver it; scrub; reboot from the new pair; let a
      spare take over; boot with a copy missing, and resilver it on its
      return.
    • make test-pci-hotplug.
  • On a Parallels virtual machine, upgraded from v1.0.10 to v1.0.11-rc1
    before this release was tagged. What its mirror did there is in
    Tested platforms.

About CosmoOS

CosmoOS 1.0.11: the 1.0 roadmap completed. CosmoOS installs to a disk, reboots into it, is used through BusyBox ash, keeps files across reboots, reaches the network by name, accepts an ssh login, and has a verified boot chain and sound randomness, on x86-64 and AArch64 under QEMU.

Start with the user guide. Each architecture's files: cosmoos-ARCH.img (the signed live image), its UEFI loader, kernel.elf, boot.tar, cmdline, the signed manifest, cosmo-upgrade and its signed package. SHA256SUMS.sig is SHA256SUMS's detached signature with the release key below (scripts/modsign.py verify-detached, or cosmo-verify on an installed system); check the files with sha256sum --ignore-missing -c SHA256SUMS.

Release signing key

The loader in these images verifies the kernel, boot archive and command line against this Ed25519 key (and the kernel trusts it for modules and packages):

  • public key: d2c778bcb38775790b6b6e843631bd2e76d6a29ec52296ece6e2d67c1bef41f8
  • key id: 36ae7bb4947896ab (the first 8 bytes of SHA-512 of the key; the boot log prints it: verified boot, key 36ae7bb4947896ab)
  • in the repository: tools/keys/release-2026.pub

Toolchain

Built and tested in the project's CI images (ci/Dockerfile), pinned by digest:

  • toolchain: ghcr.io/vkuttyp/cosmoos-ci@sha256:f6aee1470b952bdb426b8d55cfcccb734c9c1f4dac50c89edefba4e8be3be385
  • litmus: ghcr.io/vkuttyp/cosmoos-ci@sha256:c8b16f9c652cd99e4a557c08adc451528cc9cd36ba0e9e37b2973feffb15a5a9
  • clang 1:19.0-63
  • lld 1:19.0-63
  • llvm 1:19.0-63
  • qemu-system-x86 1:10.0.13+ds-0+deb13u1
  • qemu-system-arm 1:10.0.13+ds-0+deb13u1
  • ovmf 2025.02-8+deb13u1
  • qemu-efi-aarch64 2025.02-8+deb13u1
  • mtools 4.0.48-1
  • python3 3.13.5-1
  • clang-19 1:19.1.7-3+b1
  • lld-19 1:19.1.7-3+b1
  • llvm-19 1:19.1.7-3+b1

Third-party sources

Fetched and checked against these SHA-256 digests (ports/busybox/busybox.mk, ports/dropbear/dropbear.mk, ports/openssh/openssh.mk, ports/mbedtls/mbedtls.mk):

Source Version SHA-256
BusyBox 1.37.0 3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4
musl 1.2.5 a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4
compiler-rt 19.1.7 c12b6e764202c615c1a3af9a13d477846878757ae0e29e5f8979215a6958fffc
dropbear 2026.94 e098034a843699200c8c977a991fff73159735bf795d5f72ef672c41a6b1ae81
OpenSSH portable (sftp-server only) 10.6p1 a9dc9565dffe8640f64d863cd29a32bc4a3dbdec0566a7fc44c5d6ee767d5f39
mbedTLS 3.6.7 a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6
CA certificates (curl's extract of Mozilla's) 2026-09-25 a41b5d356aea97a529fe27e0f7316d2f9d946d75927476cf9cf1b90637d00505

Reproducibility

Each architecture was built twice from the tag v1.0.11, in two fresh containers of the toolchain image above, with the release key; every file below was identical in both:

  • x86_64: two builds, 10 files each, identical; cosmoos-x86_64.img sha256 585acac619da1273718fbdf73f37446d2488f4d0c1233918417ff4e8aeb31cb4
  • aarch64: two builds, 10 files each, identical; cosmoos-aarch64.img sha256 bd523b1797eb3eee003c38c0c3547c58924fa8ed80f5996867c9b518aa03b77c

To rebuild: check out the tag, run the toolchain image above, and make ARCH=<arch> SIGNING=release MODSIGN_KEY=<key> KEYRING_PUBS=tools/keys/release-2026.pub release. Without the private key, a build with your own key differs in what the key reaches: the key ring compiled into the kernel and loader, the signatures on modules, packages and the manifest, and the archive and image that hold them.

SHA256SUMS

585acac619da1273718fbdf73f37446d2488f4d0c1233918417ff4e8aeb31cb4  cosmoos-x86_64.img
115ef94c7916d2ba01ed3127701506beb2cc8199f6835a4e4489966fa34ffb67  cosmoos-x86_64-BOOTX64.EFI
a4e02b784d344b30de5980632fc58553de74930419c8a0f6f38f38c5f57afc01  cosmoos-x86_64-kernel.elf
f4ca8fdbf1e1ef8d8a7e92f1877ff4c80b8393793401e9b68ab5c5969e7d6a6a  cosmoos-x86_64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-x86_64-cmdline
b15fcdd85e640745aa862705b2d9f1e2ddbcb5a13411cc5694caf74a509b510e  cosmoos-x86_64-manifest
e8d3475826bfd1d013cc078a6ebaedb1142518949fab105c005a8890b2b11960  cosmoos-x86_64-cosmo-upgrade
e6b9a0b4f8d6ab0d9bde7fc7567585d813ae2dcba22874c98e5cf58a7fb4e28b  cosmoos-x86_64-cosmo-upgrade.cpk
bd523b1797eb3eee003c38c0c3547c58924fa8ed80f5996867c9b518aa03b77c  cosmoos-aarch64.img
0d00053d85654789deaf9fa0edc5cb8231d8d142140c1198bcb38cfedc8ff87e  cosmoos-aarch64-BOOTAA64.EFI
d1f75dbe0ef90c925c71de81141665f71796c9bb67c555e6c2546ff36fcee045  cosmoos-aarch64-kernel.elf
a5119fc33f81ba28f581c84b492dbebb5f76e01d84487f958457838bc287bdf8  cosmoos-aarch64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-aarch64-cmdline
02d8702bd4c21d6bfb0d66c94d0d5df451d25eb638f01cd733d69bea16aed7cd  cosmoos-aarch64-manifest
8d25dc5353238833fb56e7d2f1673a08d0094f0e6dfa20268a02011373ba8444  cosmoos-aarch64-cosmo-upgrade
4b8f6c0445747f4e1eed66686446d79177f4406b5c6d33edcc7e76f118e8f4af  cosmoos-aarch64-cosmo-upgrade.cpk

Known limitations

What CosmoOS 1.0 does not do, or does differently from what you may
expect. Each item names where it is recorded; the work that remains
after 1.0 is in docs/plan.md, and the full list of known
gaps in the deferred-work inventory.

Machines

  • QEMU is the tested platform. x86-64 on q35 and AArch64 on virt
    are tested by CI; there is no physical hardware matrix. Since v1.0.1
    the AArch64 image boots on Parallels Desktop 27 on Apple Silicon, and
    since v1.0.3 installs on its NVMe disks and has a network there; its
    SATA disks are not seen (Tested platforms). Out of scope for 1.0
    (roadmap): GPU and display beyond a text console (on
    the firmware's framebuffer, or a virtio-gpu adapter at the display's
    own size: no 3D, cursor or display interface for programs), CPU and memory
    hotplug (PCIe disks can be added and removed since v1.0.11), NUMA, more than 64 CPUs, huge pages, live migration,
    RAID-Z, eBPF, and the Intel VMX backend on hardware.
  • Randomness from the weakest source last. The pool seeds from the
    CPU's random instructions, the firmware's EFI_RNG_PROTOCOL or a
    virtio-rng; with none of them (Parallels Desktop) a timing-jitter source
    seeds it, credited conservatively (docs/kernel/security/design.md §6).
    random.jitter=off on the command line turns that off, and the pool
    then never seeds there. The commands in this guide add -device virtio-rng-pci.
  • The clock is stepped, not slewed. The wall clock is set at boot
    from the RTC or, with none (Parallels), the firmware's time. Since
    v1.0.4 root can set it (date -s, hwclock -w where there is an RTC)
    and ntpd -q steps it once from a server; there is no NTP daemon,
    because adjtimex is not implemented, and no time zone.
  • No Wi-Fi, Bluetooth or sound.

Boot and security

  • Verified boot covers the loader's three files (kernel, boot archive,
    command line). The root filesystem is not verified; the loader is
    not signed for UEFI Secure Boot; there is no TPM measurement
    and no rollback protection for manifests or modules (inventory
    2.9).
  • No KASLR: the kernel is at a fixed address. User-space ASLR covers
    the stack, heap, mmap and PIE executables; a non-PIE (ET_EXEC)
    program loads at its fixed address.
  • One user, root. Privileges, not uids, separate what processes may
    do (Privileges). A root session holding fewer
    privileges can still rewrite files in /etc that a later boot runs
    with all of them (M5 report, inventory 2.9).

Shell and commands

  • The commands are the BusyBox applets listed in the shell
    page
    : no ping6; no hard links; no /sys.
  • /proc has the process directories and a fixed set of system files
    (meminfo, stat, loadavg, uptime, mounts, version,
    cpuinfo). A process has no nice value and no user/system split of its
    CPU time; ps's TT column is a pair of Linux device numbers (5,1
    for the console), since devices here have none of their own; and a
    process's environ is what exec gave it, not what it has since written
    over (inventory §13).
  • The terminal driver honours the common modes (canonical input, echo,
    signals, raw mode, window size); most other termios flags and control
    characters are accepted and ignored (inventory 1.4).
  • No swap.

Networking

  • wget's certificate authorities are fixed in the image
    (/etc/ssl/certs/ca-certificates.crt, as built); nothing updates them,
    and there is no certificate revocation check
    (Networking).
  • The address comes from DHCP. There is no runtime tool to set one by
    hand; /etc/resolv.conf is written once per boot, not on lease
    renewal; the DHCP client does no ARP probe or DECLINE, no INIT-REBOOT,
    no RELEASE, and ignores classless routes (option 121) (inventory 2.5).
  • IPv6 is link-local; there is no IPv6 routing beyond the link, no IP
    fragmentation, and no TCP SACK, window scaling or timestamps
    (inventory 2.5).
  • ssh is dropbear with key login only (Ed25519 or RSA), root only;
    no port forwarding (ssh).

Storage

  • cosmofs files are capped at 516128 blocks of 4 KiB (about 1.97 GiB),
    64516 blocks (252 MiB) when encrypted; a larger write fails with
    EFBIG.
  • A read-only mount still writes the replay of an interrupted free or
    orphan record, as a journalling filesystem replays its journal.
  • A rollback to a snapshot takes effect at the next boot (or the next
    mount of another filesystem), not in the running system
    (Snapshots and rollback); a clone of a clone, and a
    snapshot of a clone, are not possible; no RAID-Z (backlog CFS-13). A
    mirror holds at most four copies (backlog CFS-27), and a copy missing when the pool is
    mounted is rebuilt whole when it returns, not caught up (backlog
    CFS-29; Mirrors).
  • A root disk that appears late (USB storage) is not waited for: init
    stays on the live root and says so.

Packages

  • A network repository is fetched whole, file by file: no mirrors, no
    delta updates. Its index's freshness is only as good as the clock, which
    is stepped by hand or by ntpd -q, with no NTP daemon
    (Packages).
  • cosmo-upgrade --rollback returns packages and /etc only to a boot
    environment, which upgrades made by v1.0.8's cosmo-upgrade and later
    take; past an upgrade made by v1.0.7 or older it returns the boot set and
    the base system only (Upgrading). Only
    files under /root, /home and /var/log written after the upgrade
    are kept across a rollback; the root is rolled back at the next boot,
    never while it runs; one pool.

Linux programs

  • Static and PIE Linux binaries for x86-64 and AArch64 run under the
    Linux personality; it is a subset of Linux's system calls, so a
    program that needs a missing one gets ENOSYS. Dynamically linked
    musl programs run through musl's own linker, /lib/ld-musl-$ARCH.so.1,
    with libc.so and dlopen; glibc's has not been
    tried. A library with text relocations is refused (W^X); build it
    -fPIC. Native CosmoOS programs stay static.
    No containers or desktop software (docs/plan.md).