# AGENTS.md ## What this repo is NixOS flake that defines kiosk systems running the RadiantWave app. Not application code — this is the OS image and deployment configuration. The actual app lives in the `radiantwave` flake inputs (from gitea.radiantwavetech.com). Hosted on Gitea: `https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig` ## Prod/dev split Single branch (`main`) for this repo. The production vs. dev split is at the **flake input + upgrade ref** level: - Production variants consume the `radiantwave` input (`?ref=main`) and auto-upgrade from `KioskConfig.git#` on `main`. - `-dev` variants consume the `radiantwave-dev` input (`?ref=dev`) and auto-upgrade from `KioskConfig.git?ref=dev#-dev`. Both gitea repos are public: all git access is plain HTTPS (`git+https://...`), no SSH keys or access tokens on the kiosks. Don't reintroduce `git+ssh` URLs in flake/upgrade refs. ## Key commands ```bash # Build a system closure (any config name from flake.nix) nix build .#nixosConfigurations..config.system.build.toplevel # Build a bootable ISO nix build .#nixosConfigurations..config.system.build.isoImage # Deploy to a remote kiosk over SSH nixos-rebuild switch --flake .# --target-host root@ # Push build result to Attic cache (not currently wired into any config) attic push kiosk ./result # Evaluate available config names nix eval .#nixosConfigurations --apply builtins.attrNames ``` ## Config variants | Name | Target hardware | Disk device | App input | |---|---|---|---| | `radiantwavekiosk` | Intel NUC 14 (NVMe) | `/dev/nvme0n1` | `radiantwave` (main) | | `radiantwavekiosk-dev` | Intel NUC 14 (NVMe) | `/dev/nvme0n1` | `radiantwave-dev` (dev) | | `radiantwavekiosk-commercial` | Commercial HW (SATA) | `/dev/sda` | `radiantwave` (main) | | `radiantwavekiosk-commercial-dev` | Commercial HW (SATA) | `/dev/sda` | `radiantwave-dev` (dev) | | `radiantwavekiosk-android` | Intel NUC 14, rotated display | `/dev/nvme0n1` | `radiantwave` (main) | | `radiantwavekiosk-android-dev` | Intel NUC 14, rotated display | `/dev/nvme0n1` | `radiantwave-dev` (dev) | | `radiantwavekiosk-rpi` | Raspberry Pi 5 (SD image) | — | `radiantwave` (main) | | `radiantwavekiosk-rpi-dev` | Raspberry Pi 5 (SD image) | — | `radiantwave-dev` (dev) | Every variant sets its own `networking.hostName` (same as the config name) and `system.configurationRevision`, so `tools/find_systems.zsh` can identify fleet members. ### USB images (zero-touch installers) Each ISO installs exactly one closure using that closure's disk layout (`mkIso` in `flake.nix` derives both from the target config name): | ISO | Installs | Disk layout | |---|---|---| | `kiosk-iso` | `radiantwavekiosk` | NVMe (`disk-config.nix`) | | `dev-iso` | `radiantwavekiosk-dev` | NVMe | | `commercial-iso` | `radiantwavekiosk-commercial` | SATA (`commercial-disk-config.nix`) | | `commercial-dev-iso` | `radiantwavekiosk-commercial-dev` | SATA | | `android-iso` | `radiantwavekiosk-android` | NVMe | | `android-dev-iso` | `radiantwavekiosk-android-dev` | NVMe | The installer lives once in `zero-touch-installer.nix` and is parameterized by `targetConfig`. Adding a new variant = add the `nixosConfigurations.*` entry, a matching `packages.x86_64-linux.*` line, and an ISO if needed. Raspberry Pi systems are built as SD images, not ISOs: `nix build .#nixosConfigurations.radiantwavekiosk-rpi.config.system.build.sdImage` (see `build-rpi.sh`). ## Hardware facter reports `facter.json` is a hardware report captured on a **NUC 14**. It is currently applied to **every x86 variant**, including the commercial SATA hardware — acceptable until per-model reports exist. To generate a report for a hardware model: 1. Boot that hardware from any NixOS live image (the kiosk installers work). 2. With real peripherals attached (display(s), audio), run: ```bash sudo nix shell nixpkgs#nixos-facter -c nixos-facter -o facter-.json ``` 3. Commit `facter-.json` to the repo root. 4. Wire it up at the marked spot in `flake.nix` (`facter.reportPath` inside `mkKioskSystem`) by selecting the right file per variant. Regenerate when major hardware changes, not on a schedule — reports are snapshots. RPi configs don't use the facter module, so no report is needed there. ## CI (Gitea) `.gitea/workflows/build-*.yml` — all triggered by `workflow_dispatch` on the `build-server` runner. They only **build and publish** what is committed. `flake.lock` is updated manually: commit an updated lock (e.g. after `nix flake update radiantwave-dev`) and dispatching the workflow is the release trigger. ## Important gotchas - **Disk device differs by variant**: `disk-config.nix` uses `/dev/nvme0n1`, `commercial-disk-config.nix` uses `/dev/sda`. `mkIso` pairs each ISO with the correct layout automatically — keep new ISOs paired correctly. - **Changing a config name** requires updating that config's `upgradeFlakeRef` in `flake.nix` (it embeds the name). - **`rotated_display.nix` uses `mkForce`** on `loginShellInit` — it replaces the entire kiosk startup script from `configuration.nix`; don't edit both. - **Auto-update**: `system.autoUpgrade` runs every 10 min (`*:00/10`) with `--refresh`, operation `switch`, no auto-reboot. A `radiantwave-backup` rsync runs before each attempt. The health-check/rollback service is written but commented out in `configuration.nix`. - **No binary cache**: kiosks fetch from cache.nixos.org only and compile RadiantWave itself from source during upgrades. Attic integration was planned (see `PLAN-update-system.md`) but never wired; the old netrc/JWT setup has been removed. - **Secrets**: none in-tree anymore (gitea repos are public). If either repo goes private, re-add auth via `nix.settings.access-tokens` in `configuration.nix`. - **Flake inputs**: `radiantwave` tracks main, `radiantwave-dev` tracks `?ref=dev`; prod and `-dev` configs consume them respectively. Updating them independently is intentional. - **SSH keys on machines are inbound-only** (`authorizedKeys` for admin access); outbound git is HTTPS. The root key in `zero-touch-installer.nix` must stay in sync with `myKey` in `configuration.nix`. ## File map - `flake.nix` — entry point: inputs, builders (`mkKioskSystem`, `mkRpiKioskSystem`, `mkIso`), all system definitions, facter report wiring - `configuration.nix` — shared NixOS config (packages, services, kiosk user, auto-upgrade, health check, VM variant) - `zero-touch-installer.nix` — parameterized USB installer module used by all six ISOs - `disk-config.nix` — NVMe disk layout (NUC) - `commercial-disk-config.nix` — SATA disk layout (commercial HW) - `rotated_display.nix` — portrait display override for Android variant - `facter.json` — hardware facter report (NUC 14) - `assets/` — logo and splash image - `plymouth-theme/` — boot splash theme - `tools/find_systems.zsh` — subnet sweep for fleet inventory over SSH - `build-rpi.sh` — containerized RPi SD-image build helper - `PLAN-*.md`, `report.md`, `timeline.csv`, `kiosk-url-changes.csv` — planning/history notes, not configuration