Repository navigation
CosmoOS 1.0.7
The package index lasts 90 days
The project's package index was signed for 30 days and renewed by a
weekly job. GitHub stops a scheduled job after 60 days without activity
in the repository, so a quiet repository would have left every installed
system's pkg update refusing an expired index. Now:
INDEX.90, signed for 90 days, sits beside the 30-dayINDEX;
both carry the same serial. This release'spkgreadsINDEX.90
first, andINDEXonly when the server has noINDEX.90. Both are
checked in the same way, and a replayed index is still refused.- Every release and pre-release signs both again, as the weekly job
does, and the release checklist starts the job by hand after a quiet
month. - An expired index is refused with one sentence, which names its
expiry and serial and says that the repository must be signed again.
pkgexits non-zero and keeps the stored index.
Systems on v1.0.6 need no action beyond their next pkg update. They
keep reading the 30-day INDEX, which is still signed weekly and at
every release. After moving to this release they read INDEX.90.
An installed system's /tmp is now mode 01777, so every user can write
there. It was 0755, owned by root.
Fixes from the Parallels test
- A large read is filled.
dd if=/dev/zero bs=1M count=4copies
four whole records. A read of a regular file or/dev/zeroused to
stop at 64 KiB. The read is one operation: another reader or a seek
on the same open file never lands in the middle of it. wgetrefusing a certificate now ends on the TLS library's reason.
Before, it addedwget: error getting response: Resource temporarily unavailable.- No free-count warning at mount: every mount of a cleanly unmounted
disk warned that the superblock's free count differed from the
bitmap's. The comparison now runs before the free-log replay, not after
it. - A Linux program's
writevis one write, as on Linux: a line a
program prints is no longer split on the console by a kernel message,
and a datagram socket sends the vector as one datagram. sftp's?link count is not a defect. It is how OpenSSH's own
client renders a long listing, as on Linux; the file's count on the
server is right (stat -c %h).
Shared libraries
Linux programs can now be dynamically linked against musl:
-
/lib/libc.so, which is also musl's dynamic linker, with
/lib/ld-musl-x86_64.so.1(orld-musl-aarch64.so.1) linking to it.
This is the interpreter every dynamic program names.dlopen,RUNPATH
and thread-local storage work. Libraries load at random addresses on
every run. -
/bin/busybox.dynis BusyBox dynamically linked, with a link for
each applet under/usr/bin. It passes the same scripted test and
BusyBox testsuite as the static/bin/busybox, which stays the shell.
/bincomes first inPATH, so nothing changes until you ask for it:cosmo$ /bin/busybox.dyn sh -c 'echo hello from a dynamic shell' cosmo$ PATH=/usr/bin:$PATH ls -l /libThe package
busybox-dyninstalls the same binary. -
The kernel tells the linker the truth.
AT_SECUREis set when the
effective ids are not the real ones, and musl then ignores
LD_LIBRARY_PATHandLD_PRELOAD.AT_HWCAPandAT_HWCAP2carry
the CPU's features.statreports a device number per mount. -
Text relocations are refused. A library that needs writable,
executable code cannot load under W^X, and the kernel log says to
build it-fPIC. -
pkgknows libraries. A package records the libraries it provides
and requires.pkg installrefuses a package whose library nothing
provides.pkg removerefuses to remove a library another package
still needs.
Native CosmoOS programs stay static.
Upgrading from v1.0.6
Run cosmo-upgrade --fetch v1.0.7 twice. The first run is v1.0.6's
program, which does not know /lib. It installs everything else,
including the new cosmo-upgrade. The second run uses that new program:
it finds the set already current, finishes, and adds /lib. Then reboot
and run pkg update && pkg upgrade. Without the second run the system
works, but /bin/busybox.dyn cannot start. From v1.0.5 and earlier,
follow the guide's "Fetching directly" page with this release's package.
Its cosmo-upgrade installs /lib in one run.
Tested: on every change and on both architectures, make test-busybox
(the static and the dynamic BusyBox, dlopen), make test-pkg-net (the
expiry sentence, INDEX.90 and the fallback to INDEX), make test-install (/tmp, no free-count warning) and make test-net-login
(the refused certificate, sftp).
About CosmoOS
CosmoOS 1.0.7: 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.7, 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 d6402ad061794d0d0df5b6d359532156e2312e398ca4cdf10d990689de779f34
- aarch64: two builds, 10 files each, identical; cosmoos-aarch64.img sha256 4781f61b65840258f887d5e384ba48cb105474336a5fd5e948b0ccdcce70e6e5
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
d6402ad061794d0d0df5b6d359532156e2312e398ca4cdf10d990689de779f34 cosmoos-x86_64.img
115ef94c7916d2ba01ed3127701506beb2cc8199f6835a4e4489966fa34ffb67 cosmoos-x86_64-BOOTX64.EFI
2d22b4e133071f93919bb0ca605a0a9e226261d435c30d29d553dbc5d8faa245 cosmoos-x86_64-kernel.elf
0372e739d19ce38df510b1c5260349daa39673863f7194ab9d235930909dc7f3 cosmoos-x86_64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14 cosmoos-x86_64-cmdline
e065a006cf80fddbdad1f8f21ca89740355fb05b7440e3bb2feaf84911f1e85e cosmoos-x86_64-manifest
78ed33b1b37f95103b1d5445396cdd7b4d414b96e16ba1bc0a4191a24ae3a16b cosmoos-x86_64-cosmo-upgrade
2ebce34d1bba4b065a7da396a57c7f41531c722e116c8b7b86b104793a47c88e cosmoos-x86_64-cosmo-upgrade.cpk
4781f61b65840258f887d5e384ba48cb105474336a5fd5e948b0ccdcce70e6e5 cosmoos-aarch64.img
0d00053d85654789deaf9fa0edc5cb8231d8d142140c1198bcb38cfedc8ff87e cosmoos-aarch64-BOOTAA64.EFI
23dc87987acae3cd537813f804b2ea56803cc55a26e6ce421c5257728cb262ae cosmoos-aarch64-kernel.elf
bf1357a0c748f841de762e69ea55260451739ac3d3d2a0a887dd5a06404a6b3e cosmoos-aarch64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14 cosmoos-aarch64-cmdline
851e8df9b83811bb825026a24e54139d9bd535fbb0ad7a6451c6da7699787739 cosmoos-aarch64-manifest
84729ab387e6355713c533d1cc63f126c861507c5c725924bab1cca079c328bd cosmoos-aarch64-cosmo-upgrade
bd9401af2a36481369df0ab58ac303c689086172f9c487c7f616d906fd053737 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
q35and AArch64 onvirt
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'sEFI_RNG_PROTOCOLor 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=offon 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,mmapand 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/etcthat 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: noping6; no hard links; no/sys. /prochas 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'sTTcolumn is a pair of Linux device numbers (5,1
for the console), since devices here have none of their own; and a
process'senvironis 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.confis 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
packagespkg upgradechanged.
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 getsENOSYS. Dynamically linked
musl programs run through musl's own linker,/lib/ld-musl-$ARCH.so.1,
withlibc.soanddlopen; 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).