Releases: xinix00/HopOS
Release list
HopOS v1.5.5
Every flavor now boots with something. Both the GUI and the headless assets ship a working default hopos.cfg — one edit required (hopos.apikey), then boot:
- GUI: a ready-made desktop — display, launcher and the app catalog straight from the hop-os-surf rolling release, no addresses to fill in.
- Headless: a bare node waiting for work over the HOP API, with commented
hopos.init[]lines in the template to seed your own baseline.
Editing that file on the FAT partition is node management: no shell, no rebuild. The Pi 4 gains the same initramfs hopos.cfg boot recipe as the Pi 5 (full JSON job specs, no bootargs size limit).
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI + hopos.cfg — any UEFI arm64 box: EFI to
EFI/BOOT/, config in the stick root - hopos-rpi5.zip / hopos-rpi4.zip — unzip onto the SD bootfs (config included)
*-headless— the same images with zero GUI code linked;hopos-headless.cfgis their config template. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.5.4 — hairpin
Hairpin NAT. Publish ports outward, let DNS pick the host — and when that host happens to be your own node, the switch takes the shortcut. A slot dialing the node IP on a published port is redirected internally: DNAT + masquerade in a single pass over the two existing tables (no new state), delivered ring-to-ring — not a byte leaves the NIC. Reply recognition is unambiguous: only a neighbour slot can carry the node IP as a destination (masquerade replies arrive via the uplink). Covered both ways by hairpin_test.
This retires the last-but-one deliberate KISS gap from day one; the remaining one (node IP from inside for unpublished ports) stays — node services live on 10.100.0.1.
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
*-headless— the same images built withGUI=0: not a disabled GUI but zero GUI code linked. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.5.3
apphttp bugfix. Serve's accept loop could spin when the app netstack returned a temporary error or an empty accept (nil, nil) — eating the entire core: the SURF display sat at 100% CPU, never answering, without a single log line. net/http has a safety net here (growing back-off on temporary errors); apphttp lacked it, and that difference was exactly the difference between a working and a dead display.
Fixed: exponential back-off (1ms→100ms) on temporary errors, and an empty accept without an error now ends the loop with a reason — fail loudly, so the app logs it and the node restarts it. Pinned by a regression test (TestServeNeverSpins).
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
*-headless— the same images built withGUI=0: not a disabled GUI but zero GUI code linked. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.5.2
Built against HOP v0.20.1.
No capacity is pending, not a crash. A placement failure (no free core, pool doesn't fit) is now marked hopos.ErrNoCapacity, so HOP parks the job as unplaceable instead of restart-looping it — every retry used to re-download the image just to fail again.
The two-sharegroup desktop recipe ships in hopos.cfg.example and docs/config.md: desktop packs the display + launcher chrome on one core; apps stacks every window app on the remaining cores (cpu_shares sizes the pool, not a per-app quota) — so the eighth window is just another cage on the pool, not a rejection. The catalog pulls straight from the hop-os-surf rolling release.
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
*-headless— the same images built withGUI=0: not a disabled GUI but zero GUI code linked. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.5.1
apphttp, both ways. The plain-HTTP client gained Do (method, body, chunked decoding) and a small Serve joins it — apps that serve a page (like the SURF display) no longer link net/http. Measured on the SURF apps: display 8.68 → 5.88 MB, launcher 8.42 → 5.48 MB, taskman 8.45 → 5.54 MB — zero crypto/tls symbols in the binary. The browser keeps net/http: it talks https to the outside world.
Desktop config from the rolling release. hopos.cfg example config now pulls the display/launcher artifacts straight from the hop-os-surf rolling release — same URL on every node, no file server of your own — and packs both onto one core via the desktop sharegroup, leaving every other core free for real apps.
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
*-headless— the same images built withGUI=0: not a disabled GUI but zero GUI code linked. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.5.0 — the review release
A full review pass, applied — net −800 lines at the same feature set:
- One netstack. The lneto appnet variant is gone (dependency removed); gVisor's netstack is the stack.
- Dead-peer detection moved to where it belongs. The switch no longer forges TCP RSTs on behalf of dead apps — silence can always be the network, and two layers already cover it (the task health check and the app's own ping). See
docs/technical/networking.md. - apphttp: a minimal plain-HTTP/1.1 client for apps, as a separate package —
net/httpunconditionally links crypto/tls, measured onapp/hello: applib alone 1.71 MB, + netstack 4.70 MB, + net/http 7.99 MB. Only who imports it pays. - Leaner GUI node side: the node keeps only the DeviceGrant (
gui/fbgrant); the display-controller and compositor stack live app-side in the companionhop-os-surfrepo. Every image builds bare or gui (GUI=0) — a bare node never gives away the glass. - hopos.cfg.example: a secrets-free sample next to the gitignored real config, so a fresh clone sees exactly what a node needs.
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
*-headless— the same images built withGUI=0: not a disabled GUI but zero GUI code linked. For UEFI, renameBOOTAA64-headless.EFItoBOOTAA64.EFIon the stick.
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.4.0 — SURF
SURF — a GUI on cores, not processes. A real desktop on HopOS: a display app owns the screen through the display controller (planes — still no GPU driver), and apps draw over SURF, a network protocol — so a window can come from any core on any node in the cluster. The kernel only gained a seam: DeviceGrants lend a plane window into an app's cage for the duration of its lifecycle; built without the gui flavor, no grant exists. The boot medium can now carry a full desktop: hopos.init[] starts the display + launcher, hopos.apps[] is the launcher's catalog.
KILL on PANIC. A fatal panic used to burn a dedicated core until powercycle (tamago's halt is a corpse the stage-2 revoke can't even reach). Now the runtime's exit hook hands the core back to HopOS cleanly, and peers get a TCP RST at teardown instead of a connection that hangs forever.
Prebuilt, signed boot images — https://gethop.org/hopos/ for the 5-minute quickstart.
- BOOTAA64.EFI — any UEFI arm64 box: copy to
EFI/BOOT/on a FAT USB stick, addhopos.cfg - hopos-rpi5.zip — Raspberry Pi 5: unzip onto the SD bootfs
- hopos-rpi4.zip — Raspberry Pi 4: unzip onto the SD bootfs
Verify: ssh-keygen -Y verify -f allowed_signers -I hello@gethop.org -n gethop-release -s SHA256SUMS.sig < SHA256SUMS && shasum -a 256 -c SHA256SUMS
HopOS v1.3.1
Init jobs on the boot medium: hopos.init[]={...} in cmdline.txt (Pi) or hopos.cfg (UEFI) seeds jobs on a clean boot — one compact-JSON job per entry, same schema as the jobs API, repeatable. A standalone node without S3 always boots clean and thus always comes up with exactly this baseline: a fully self-contained node on a stick. With S3, entries seed the first clean boot only.
HopOS v1.3.0 — sharegroups
Cooperative core sharing, strictly opt-in. A sharegroup packs apps you explicitly name onto a shared pool of whole cores: members hand the core over when idle (explicit yield — no timer, no preemption), each still inside its own stage-2 cage with its own network stack. Sharing never happens involuntarily — ungrouped apps keep the full whole-core guarantee. Small boards now fit more apps than cores.
Prebuilt signed images attached below.
HopOS v1.2.2
Per-app CPU% — derived from the idle-time signal each app already publishes on its control page, averaged over a 5s window into a docker-style cpu_percent (SMP-normalized). The idle governor now counts actual idle time instead of wake ticks, making the measurement noise-immune on real hardware. Completes the per-task observability set: memory draw, temperature, CPU utilization.