No description
Find a file
Breadway 22a8db09a6
All checks were successful
Mirror to GitHub / mirror (push) Successful in 3s
Build and publish yay-bin / yay-bin (push) Successful in 22s
Fix mkinitcpio hook detection: current default is systemd-based, not udev
Verified against the actual cached mkinitcpio package (41-4), not assumed:
its shipped /etc/mkinitcpio.conf template is
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole
block filesystems fsck) — there's no "udev" token at all on a stock
install anymore, systemd is the base hook instead.

This silently broke two things:
- The existing plymouth-hook insertion (`sed 's/\budev\b/\0 plymouth/'`)
  has been a no-op on every fresh install using a current mkinitcpio
  package — the boot splash was never actually getting wired into the
  initramfs, just failing quietly (the script's best-effort `|| echo WARN`
  pattern doesn't catch a sed that "succeeds" by matching nothing).
- My own new encrypt-hook insertion from the previous commit had the same
  flaw, and would have used the wrong hook regardless: `encrypt` is the
  udev-based hook, systemd-based initramfs needs `sd-encrypt` instead.

post-install.sh now detects which base hook (systemd or udev) is actually
in HOOKS once, and uses the matching hook name for both plymouth
(unaffected by the choice, just needed the right anchor to insert after)
and LUKS unlocking (encrypt vs sd-encrypt — genuinely different hooks).

Also: avoid a redundant pacman -Sy in release-iso.yml's signing step —
the job already synced repos earlier in the same container.
2026-07-04 11:20:01 +08:00
.forgejo/workflows Fix mkinitcpio hook detection: current default is systemd-based, not udev 2026-07-04 11:20:01 +08:00
assets v0.4.0: branding refresh, breadpaper baked in, bos-settings 0.4.0 2026-06-18 14:50:44 +08:00
bos-settings bos-settings 0.6.0: Power, Firewall, Users, AUR, Firmware panels 2026-07-04 11:04:16 +08:00
dotfiles Fix boot-critical, session, and UX bugs found in round-3 UX audit 2026-07-03 22:04:26 +08:00
iso Fix mkinitcpio hook detection: current default is systemd-based, not udev 2026-07-04 11:20:01 +08:00
packaging Ship yay, wire up LUKS disk encryption, self-signed Secure Boot, release signing 2026-07-04 10:39:44 +08:00
scripts docs+test: ecosystem matrix, keybinds, limitations, recovery, smoke test 2026-06-16 15:51:47 +08:00
.gitignore Minor cleanups: gitignore out/, expect() messages, comment wording 2026-06-17 22:57:58 +08:00
bakery.toml Add bakery.toml and packaging/arch to match bread ecosystem 2026-06-13 11:32:40 +08:00
build-local.sh Fix install-breaking and live-boot bugs, verified on real hardware 2026-07-03 13:31:40 +08:00
Cargo.lock bos-settings 0.6.0: Power, Firewall, Users, AUR, Firmware panels 2026-07-04 11:04:16 +08:00
Cargo.toml Scaffold BOS repo: dotfiles, ISO profile, and bos-settings GTK4 app 2026-06-12 13:27:25 +00:00
DESIGN.md Fix prod-readiness issues flagged in audit 2026-06-13 11:29:53 +08:00
KEYS.asc Ship yay, wire up LUKS disk encryption, self-signed Secure Boot, release signing 2026-07-04 10:39:44 +08:00
LICENSE Add bakery.toml and packaging/arch to match bread ecosystem 2026-06-13 11:32:40 +08:00
README.md bos-settings 0.6.0: Power, Firewall, Users, AUR, Firmware panels 2026-07-04 11:04:16 +08:00

BOS — Bread Operating System

An Arch-based, Hyprland desktop distribution that ships the bread ecosystem preconfigured. One Calamares install produces a themed, bootable Wayland desktop — no manual Arch bootstrap, no wiring up dotfiles, no per-tool bakery installs.

Design rationale and the btrfs/A-B roadmap live in DESIGN.md. This file is the practical overview: what's in the image, how to build it, and how to test it.

What you get

  • Compositor: Hyprland with a native-Lua config (hyprland.lua), curated keybinds, snappy animations, blur, and pywal-driven colours on a black base.
  • bread ecosystem, baked into /etc/skel from bakery-managed binaries (no network needed at install time): bread/breadd, breadbar (status bar
    • notification daemon), breadbox (launcher), breadcrumbs (Wi-Fi profiles), breadpad (notes/reminders), breadman, and the bakery package manager.
  • bos-settings: a GTK4 control panel that configures every bread* app's config from a GUI (non-destructively), plus snapshot rollback and bakery updates. See below.
  • Login: greetd + breadgreet (bread-ecosystem's own greeter, under cage) → Hyprland session.
  • Boot splash: Plymouth bos theme (logo + spinner, black background).
  • Theming: global dark across GTK3 (Adwaita-dark), GTK4/libadwaita (color-scheme: prefer-dark), and Qt (qt5ct/qt6ct Fusion dark); Papirus-Dark icons; Bibata cursor.
  • Apps: kitty, nautilus (+ gvfs), Zen browser, VLC, loupe, gnome-text-editor, gnome-calculator, file-roller, with file associations wired in mimeapps.list. yay ships for AUR access beyond bakery's bread ecosystem + [breadway].
  • Hardware: pipewire audio, NetworkManager, BlueZ + blueman, CUPS printing with avahi mDNS discovery, TLP power management, fwupd firmware updates.
  • Resilience: btrfs + snapper + snap-pac + grub-btrfs snapshots on every pacman transaction; zram swap; ufw firewall (deny-incoming, mDNS allowed).
  • Security: full-disk encryption (LUKS, via Calamares' built-in support — cryptsetup + the matching mkinitcpio/GRUB wiring ship so an encrypted install actually boots) and self-signed Secure Boot (via sbctl, enrolled automatically at install time when the firmware is in Setup Mode).

Repo layout

bos/
├── Cargo.toml                     # workspace (members: bos-settings)
├── bos-settings/                  # GTK4 unified settings app (Rust)
│   └── src/
│       ├── config/mod.rs          # non-destructive toml_edit config layer
│       └── ui/{widgets,window,sidebar}.rs, ui/views/*.rs
├── iso/                           # archiso profile
│   ├── profiledef.sh
│   ├── packages.x86_64            # live + installed package set
│   └── airootfs/                  # files overlaid onto the image
│       └── etc/
│           ├── skel/              # default user dotfiles (hypr, kitty, gtk, …)
│           └── calamares/         # installer config + post-install.sh
├── packaging/                     # in-house PKGBUILDs for AUR-only deps
│   ├── arch/                      # bos-settings
│   ├── calamares/
│   └── bibata/
├── .forgejo/workflows/            # CI: build + publish packages to [breadway]
├── build-local.sh                 # native ISO build for this machine
└── DESIGN.md

Building the ISO

build-local.sh builds the image natively (no container) and bakes this machine's bakery-installed bread binaries into /etc/skel:

sudo ./build-local.sh              # release-quality (xz squashfs)
sudo FAST_BUILD=1 ./build-local.sh # fast dev iteration (zstd squashfs)

The ISO lands in out/bos-<date>-x86_64.iso. The script pins SOURCE_DATE_EPOCH (reproducible UUIDs) and rewrites the [breadway] repo URL to the Tailscale-reachable Forgejo registry for the build.

Why some packages are in-house

calamares, zen-browser-bin, bibata-cursor-theme, and yay-bin are AUR-only. BOS keeps a PKGBUILD for each under packaging/ and republishes the built package to the [breadway] repo via a Forgejo Actions workflow (built on the hestia self-hosted runner, published with a scoped registry token). bos-settings itself publishes the same way on a v* tag.

Verifying a release

Every tagged release ISO on the Forgejo releases page ships alongside a SHA256SUMS file and a detached signature SHA256SUMS.asc, signed by a dedicated release-signing key (not reused from anything else):

5620 3B86 A110 695A E7F3  1093 4AF3 323D 678E B5E2

The public half is committed at KEYS.asc. To verify a download:

gpg --import KEYS.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum -c SHA256SUMS

Testing in a VM

A reusable, GPU-accelerated launcher lives at ~/bos-vm/run.sh:

~/bos-vm/run.sh install   # boot the ISO installer (target disk attached)
~/bos-vm/run.sh           # boot the installed system from the disk

It uses KVM + -cpu host, 8 GiB / 8 vCPU, and virtio-vga-gl with -display gtk,gl=on (virgl) — 3D acceleration is essential for a smooth Hyprland session in QEMU. The disk lives on NVMe (not the tmpfs /tmp) to avoid memory pressure.

bos-settings

A GTK4 settings app aiming for GNOME-Settings-style parity: not just editing config files, but live system state and control, so day-to-day machine administration doesn't require a terminal.

Bread-ecosystem TOML configs are edited non-destructively: toml_edit parses the file, changes only the keys a view exposes, and writes it back — preserving comments and any keys the UI doesn't model (calendar passwords, saved-network passwords, model paths). Panels with a daemon behind them (bread, breadbox, breadcrumbs, breadsearch, breadclip) also get live systemd status + Start/Stop/Restart/Logs via a shared service_control widget, not just the config file.

Panel What it does
About System info (OS/kernel/CPU/GPU/memory/disk/uptime) + hostname
Network Wi-Fi scan/connect, Ethernet status, radio toggle
Wi-Fi Profiles (breadcrumbs) breadcrumbs.toml — settings, saved networks, profiles
Firewall ufw rules: enable/disable, add/remove, view active rules
Sound PipeWire output/input device + volume via pactl
Power Battery status/health, brightness, charge limits (hardware-dependent), TLP profile (read-only)
Date & Time Timezone, NTP sync toggle
Display (Hyprland) Connected monitors + open hyprland.lua in editor
Users Add/remove accounts, change passwords
Wallpaper (breadpaper) Set wallpaper, drives the pywal-derived accent palette
Bar (breadbar) breadbar/style.css override, live-reloads on save
Launcher (breadbox) breadbox/config.toml — launcher contexts
Clipboard (breadclip) breadclipd service control + "open history"
Notes (breadpad) breadpad/breadpad.toml — settings, model + ollama, reminders, calendar
File Search (breadsearch) breadsearch/config.toml — index/search/model + breadmill service
Daemon (bread) breadd.toml — daemon, lua, modules, adapters, events, notifications
Packages bakery installed list + updates, pacman system update
AUR Search via yay; installing opens a terminal (AUR build scripts need review)
Firmware fwupd device list + updates
Snapshots snapper list / boot-into (grub-btrfs) / delete

Build standalone:

cargo build --release -p bos-settings
cargo test -p bos-settings        # includes config round-trip tests

The bread ecosystem at a glance

Tool Role Launch
bread / breadd Reactive automation daemon — normalises hardware/compositor signals into events dispatched to Lua modules runs at login
breadbar Top status bar (workspaces, clock, stats, tray) and the notification daemon runs at login
breadbox Application launcher SUPER+Space
breadpad Notes & reminders (AI-classified, optional CalDAV sync) SUPER+U
breadman Package-manager UI SUPER+M
breadcrumbs Wi-Fi profile state machine (location-aware) CLI / BOS Settings
bakery CLI package manager for the ecosystem bakery
bos-settings Unified GTK4 control panel for all of the above + snapshots + updates SUPER+,

Keyboard shortcuts

SUPER is the Windows/Cmd key. Press SUPER+/ at any time for this cheatsheet in-session; first boot shows a short welcome (once).

Keys Action
SUPER+Return Terminal (kitty)
SUPER+Space App launcher (breadbox)
SUPER+E / SUPER+B Files (nautilus) / Browser (zen)
SUPER+U / SUPER+M breadpad / breadman
SUPER+, / SUPER+/ BOS Settings / keybind cheatsheet
SUPER+L / SUPER+N Lock / log out
SUPER+Backspace Close window
SUPER+F / SUPER+V / SUPER+T Fullscreen / float / toggle split
SUPER+Shift+V Clipboard history
SUPER+Tab Last window
SUPER+Shift+S/C/P Screenshot region→file / region→clipboard / screen→file
SUPER+arrows Move focus
SUPER+Shift+h/j/k/l Move window
SUPER+Shift+arrows Resize window
SUPER+1..0 Switch to workspace 110
SUPER+Shift+1..0 Move window to workspace
SUPER+[ / ] Previous / next workspace
SUPER+left/right-drag Move / resize window with the mouse

Known limitations

  • GPUs: ships the generic Mesa stack — AMD and Intel work out of the box. The NVIDIA proprietary driver is not included; NVIDIA users must install nvidia/nvidia-utils and set the usual Hyprland env vars after install.
  • Virtual machines: Hyprland needs GPU acceleration to be smooth. Use virtio-vga-gl + -display gtk,gl=on (virgl); plain software rendering is noticeably laggy.
  • Wayland-first: X11-only apps run through XWayland; a few may misbehave.
  • Secure Boot: self-signed only, via sbctl — BOS can't ship a Microsoft-signed shim (that needs going through Microsoft's own paid UEFI CA process). Post-install enrolls BOS's own keys automatically, but only when the firmware is already in Setup Mode (no vendor keys installed yet); otherwise it's skipped and you can run sudo sbctl enroll-keys --microsoft && sudo sbctl sign-all -g yourself later (after clearing your firmware's existing keys, if any). The installer writes both an NVRAM entry and the removable EFI/BOOT/BOOTX64.EFI fallback either way.
  • Disk encryption: full-disk LUKS is available on the installer's "Erase disk" page (Calamares' own checkbox) and on manually-created partitions — BOS ships the matching cryptsetup/mkinitcpio/GRUB wiring so an encrypted install actually boots (LUKS1, since GRUB doesn't support LUKS2 + Argon2id).
  • Snapshots assume btrfs: the snapper/grub-btrfs tooling expects the default btrfs subvolume layout the installer creates.

Recovery

An update broke something (system still boots): open BOS Settings → Snapshots and roll back, or pick a pre-update snapshot from the GRUB “snapshots” submenu at boot, then run snapper rollback from the booted snapshot.

The system won't boot (broken GRUB / lost EFI entry):

  1. Boot the BOS ISO and open a terminal (SUPER+Return).
  2. Mount the installed root and EFI, then chroot:
    mount -o subvol=@ /dev/sdXN /mnt
    mount /dev/sdXP /mnt/boot/efi      # the EFI partition
    arch-chroot /mnt
    
  3. Reinstall the bootloader (the same sequence the installer uses):
    grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=BOS --recheck
    grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck
    grub-mkconfig -o /boot/grub/grub.cfg
    

Firmware shows “no boot device”: select EFI/BOOT/BOOTX64.EFI from the firmware boot menu — the installer always writes that removable fallback.

Boot architecture notes

archiso keeps the kernel and initramfs outside the squashfs, so the installer stages them explicitly: a shellprocess@kernel step copies the kernel + ucode into the target /boot and writes a stock mkinitcpio preset before the native initcpio module builds the initramfs. GRUB is not installed by Calamares' bootloader/grubcfg modules (they leave the ESP empty in this layout) — post-install.sh runs grub-install (NVRAM and --removable) + grub-mkconfig instead, which is the sequence verified to boot.