Skip to content

CosmoOS 1.0.6

Choose a tag to compare

@github-actions github-actions released this 18 Oct 23:35
· 225 commits to main since this release
16dbec8

pkg and cosmo-upgrade fetch directly

An installed system now updates over the network, with nothing to fetch
by hand:

cosmo$ pkg update && pkg upgrade
cosmo$ cosmo-upgrade --check
cosmo$ cosmo-upgrade --fetch v1.0.7
  • The project's repository and release index are published on GitHub
    Pages, https://vkuttyp.github.io/CosmoOS/: each architecture's package
    repository under repo/ARCH/, each release's upgrade set under
    releases/TAG/ (without the images), and releases/LATEST. A fresh
    install's /etc/pkg/repos.conf names the network repository after the
    disk's own; /etc/cosmo-release.conf names the release index.
  • HTTPS with the certificate checked: both programs run
    /bin/cosmo-fetch, which makes the same checks as wget (the server's
    certificate must chain to the Mozilla CA bundle in
    /etc/ssl/certs/ca-certificates.crt, be valid now, and name the host),
    all before it sends a request. A repos.conf line can also pin the
    server's key (pin sha256:HEX). Plain http:// is refused unless the
    line says insecure. Redirects are followed only to the same host.
    Transfers that are cut resume.
  • A fresh index or none: a network repository's index carries a
    serial number, a publication time and an expiry (at most 30 days). pkg update refuses one older than the last it accepted (a replay), and one
    that has expired, so an attacker who can only replay old signed files
    cannot hold back an update for long. The project re-signs its index
    weekly. A clock before the index's publication is reported with a hint
    (date -s), not accepted. A repository that cannot be reached is only
    a warning; the disk's packages still install.
  • cosmo-upgrade --fetch TAG fetches the release's SHA256SUMS and
    its signature first, checks them against /etc/pkg/keys, then fetches
    the four set files and upgrades exactly as from a directory, with every
    check made again. cosmo-upgrade --check says whether a newer release
    is published.
  • Privileges: pkg install, upgrade and remove need the
    sys_admin privilege; pkg update, search, info and list do not.

Upgrading from v1.0.5 and earlier

These releases have no cosmo-fetch. Fetch this release's
cosmoos-ARCH-cosmo-upgrade.cpk (ARCH is x86_64 or aarch64) with wget from
https://vkuttyp.github.io/CosmoOS/releases/v1.0.6/, check it with pkg install -n, unpack sbin/cosmo-upgrade and bin/cosmo-fetch, and run
COSMO_FETCH=./bin/cosmo-fetch ./sbin/cosmo-upgrade --fetch v1.0.6
(the guide's "Upgrading" page, "Fetching directly"). Afterwards add the
network repository to the /etc/pkg/repos.conf the older installer
wrote: the first line on x86-64, the second on AArch64 (one of them):

cosmo$ echo 'cosmoos https://vkuttyp.github.io/CosmoOS/repo/x86_64' >> /etc/pkg/repos.conf
cosmo$ echo 'cosmoos https://vkuttyp.github.io/CosmoOS/repo/aarch64' >> /etc/pkg/repos.conf

Tested: make test-pkg-net on x86-64 and AArch64, on every change. The
installed system runs against repositories the test serves over HTTPS:
it refuses untrusted, expired and misnamed certificates with no request
sent, and refuses a changed package, an index signed by another key, and
a replayed or expired index. It installs and upgrades from the served
repository, fetches a release set with cosmo-upgrade, and then runs
pkg update against the published repository itself.

About CosmoOS

CosmoOS 1.0.6: 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.6, 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 f2f6cd791733a0342b08e25559c7a39c5aa30f372be417afb85b253cb8b59b88
  • aarch64: two builds, 10 files each, identical; cosmoos-aarch64.img sha256 01cff05e15f519368304eb8e64337fd3fe4c1c0b57813ed6c6df5622016bcb1e

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

f2f6cd791733a0342b08e25559c7a39c5aa30f372be417afb85b253cb8b59b88  cosmoos-x86_64.img
115ef94c7916d2ba01ed3127701506beb2cc8199f6835a4e4489966fa34ffb67  cosmoos-x86_64-BOOTX64.EFI
58533eb6c3184af7882259bb02ccde314b6b57143360c010c5c8a3a9f4f43461  cosmoos-x86_64-kernel.elf
3672af10d24bdbecb774fe47108df80339c01536558b676cc0d45ac7a5f1a875  cosmoos-x86_64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-x86_64-cmdline
e9941d30604f30a5964877b5228c4d55e7e2d4763bab5337728296c00fc14464  cosmoos-x86_64-manifest
bc3504296324bc52a7e6c539e88eebdc33b23a59eab6c09795b23ef182799387  cosmoos-x86_64-cosmo-upgrade
36d58063f39f4881e93a162cbdc192a3ae7391fd4fdb9742564ab3e0d0c5da31  cosmoos-x86_64-cosmo-upgrade.cpk
01cff05e15f519368304eb8e64337fd3fe4c1c0b57813ed6c6df5622016bcb1e  cosmoos-aarch64.img
0d00053d85654789deaf9fa0edc5cb8231d8d142140c1198bcb38cfedc8ff87e  cosmoos-aarch64-BOOTAA64.EFI
720eaeb1becc1436f3a0b7a5995f2b9da0ebb9a1074c9f1c2f36092c81b12a31  cosmoos-aarch64-kernel.elf
904df2a25701bfd23eb3bef303d58621b10c31eab1d806510f13f20e3bb2d5f3  cosmoos-aarch64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-aarch64-cmdline
51916effad612aa9aa930c6d181ba058112862755d543d6b42262f9ac275a0bf  cosmoos-aarch64-manifest
59dd09e9603b4f15107d5dbe5ee38945a491b30f3801189f6552641fc30ad1a2  cosmoos-aarch64-cosmo-upgrade
f5445833e03d5a4e329b6fb0e5d15c29f05962186e190863dee710214373ce14  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), hotplug, 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 read once. The wall clock is set at boot from the RTC
    or, with none (Parallels), the firmware's time; there is no NTP and no
    way to set it.
  • 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.
  • No cosmofs rollback to a snapshot from the running system, no clones,
    no RAID-Z, no resilvering (inventory 2.4); a deleted newest snapshot's
    id can be reused after a remount.
  • 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
    has no NTP (Packages).
  • No rollback of a completed package upgrade. cosmo-upgrade --rollback
    returns the boot set, the programs and the repository, but not the
    packages pkg upgrade changed.

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. The loader honours
    PT_INTERP, but only a stand-in interpreter has been run through it:
    no real ld.so with shared libraries, musl's or glibc's, has.
    No containers or desktop software (docs/plan.md).