# CLAUDE.md: quine-linuxQuine Linux: a bootc image on our fork of Universal Blue's Aurora (KDE,Fedora Kinoite underneath), with a live ISO that is also the installer.[README.md](README.md) explains the build, the overlay and releases;[GUIDELINES.md](GUIDELINES.md) the build/CI conventions shared with ourother apps. This file is what you'd otherwise rediscover the hard way.## Where things are- **Two repos build the image.** `quine-global-labs/aurora` (the fork,published as `forge.in.quineglobal.com/quine-global-labs/aurora:stable`and `:stable-arm64`) for changes *inside* Aurora's build; this repo's`Containerfile` for everything a `RUN` on top can do. Prefer this repo.- **Published as** `forge.in.quineglobal.com/quine-global-labs/quine-linux`(`latest`, `latest-arm64`, date and commit tags). Installed systems follow`registry.quineglobal.com/quine-linux:latest` (the same image, a pull-onlyname). There's one channel: every build of `main` reaches every machine;release tags only make downloads and a Forgejo release.- **The live ISO** (`live/`): `live/Containerfile` + `build.sh` turn the imageinto a live system; `titanoboa-build-iso.sh` is titanoboa's script with onemarked change (MokManager in `EFI/BOOT/`). The installer is Anaconda's webUI with our **Data disk** step (`live/anaconda-webui/`, built fromupstream's source at Fedora's version plus `steps.patch`).- **Kickoff** (the start menu) is rebuilt from our plasma-desktop fork,branch `quine-v<Plasma version>`, which the fork's rebase workflow makesfor each new Plasma. If it hasn't, the build stops and says so.- **libtaskmanager** (the task manager's models, in plasma-workspace) isrebuilt with `taskmanager/startup-feedback.patch`, so the launch spinnerfollows the app's systemd unit (README "Launch feedback"). `taskmanager/build.sh` takes Fedora's source RPM of the installed version; if a newPlasma moves the code, the patch stops applying and the build says so.- **Our apps** (layer-wizard, dnf-package-store, swap-watchdog) come from theforge's `quine` RPM group, built by each app's own CI; a fix to one reachesthe image on the next build. KeyMaker comes as a Flatpak from our repo,flatpak.quineglobal.com.- `installer/` and `output/` are local leftovers, not part of the build.## CI (`.forgejo/workflows/`)- `iso.yml`: every push to `main`, every `v*` tag, daily at 07:00 UTC. Buildsamd64 on `runner-x86-linux` (zeus VM) and arm64 on `runner-arm64-linux`(Tart VM on the Mac mini): image, qcow2, live ISO, uploads to MinIO(`s3.quineglobal.com`, bucket `quine-linux`). A build takes ~3 hours.Concurrency is per ref: a push to `main` cancels the running `main` build,not a tag build.- Put `[skip ci]` in a commit that can't change the image (docs, the VMtest), or it costs a 3-hour build.- `release.yml`: tags `main` (README "Releasing"). `vm-test.yml`: boots anISO on zeus's VM 107 ([docs/VM_TEST.md](docs/VM_TEST.md)).- Build steps run under `retry-on-network-error.sh` (retries on droppedfetches and on 30 minutes of silence); base-image pulls have a 60-minutelimit.## Gotchas- **The runners are NixOS:** no `/bin/bash`; scripts use`#!/usr/bin/env bash`.- **No short image names** in Containerfiles: `docker.io/library/node:22`,not `node:22`. The runners' podman asks which registry a short name means,and in CI nothing answers.- **Disk space:** podman stages whole images in `/var/tmp`; on the arm64runner that's the 54 GB root disk, separate from the 49 GB containersdisk. Jobs clear killed builds' leftovers at start and end.- **os-release:** we set `NAME`/`PRETTY_NAME` to Quine Linux but keep`ID=aurora` and `VARIANT_ID`: Universal Blue's tooling (ujust, uupd) andthe Anaconda profile (`os_id`) key on them.- **The ISO is UEFI-only** (like Aurora's); VMs need OVMF/"Enable EFI".- **Secure Boot:** the installer queues our MOK for enrollment; the next bootof anything with shim must find MokManager beside shim, or it loops.- **The forge is tailnet-only** (`forge.in.quineglobal.com`, SSH on 2200).MinIO's public name resolves to the forge VM directly on the tailnet; offit, it goes through mainframe at Hetzner and is much slower.## Testing a change- On a Quine Linux machine: `task test:stage` / `task test:boot`, and`task revert` to undo.- On a VM: Actions → **VM test** (or `task test:vm TAG=…`) puts an ISO onzeus's VM 107 and waits for its guest agent. VM 107 has a second 100 GBdisk with an ext4 partition labelled `data`, for the Data disk step. Tolook at the screen: on zeus, `vmvnc 107 capture /tmp/x.png`.## PushingCommit, then push to the forge first (`forge` remote), then GitHub (`github`remote): GitHub is a mirror, and a push that loses the race to it fails with"cannot lock ref"; check both show the same SHA.