Repository navigation
CosmoOS 1.0.6
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 underrepo/ARCH/, each release's upgrade set under
releases/TAG/(without the images), andreleases/LATEST. A fresh
install's/etc/pkg/repos.confnames the network repository after the
disk's own;/etc/cosmo-release.confnames the release index. - HTTPS with the certificate checked: both programs run
/bin/cosmo-fetch, which makes the same checks aswget(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. Arepos.confline can also pin the
server's key (pin sha256:HEX). Plainhttp://is refused unless the
line saysinsecure. 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 updaterefuses 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 TAGfetches the release'sSHA256SUMSand
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 --checksays whether a newer release
is published.- Privileges:
pkg install,upgradeandremoveneed the
sys_adminprivilege;pkg update,search,infoandlistdo 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
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. The loader honours
PT_INTERP, but only a stand-in interpreter has been run through it:
no realld.sowith shared libraries, musl's or glibc's, has.
No containers or desktop software (docs/plan.md).