Files
KioskConfig/AGENTS.md
T
NeilClack 65a6b256f9 Fix dev/prod split and dev ISOs; consolidate zero-touch installer
- Wire -dev variants to the radiantwave-dev input (?ref=dev); prod keeps main
- Fix android-dev upgradeFlakeRef (was upgrading into production config)
- Parameterize one installer module (zero-touch-installer.nix); replace the
  four near-duplicate ISO configs; mkIso pairs each ISO with its closure +
  disk layout, fixing commercial-dev/android-dev ISO eval errors
- Add missing packages outputs (commercial-dev, android-dev, rpi, rpi-dev)
- Set networking.hostName + system.configurationRevision per variant
- Remove gitea access token and dead netrc/JWT config (repos are public)
- Drop flake.lock update step from CI (lock updates are manual)
- Refresh AGENTS.md: variants/ISO tables, facter report procedure, gotchas
2026-08-23 09:58:46 -05:00

7.0 KiB

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#<config> on main.
  • -dev variants consume the radiantwave-dev input (?ref=dev) and auto-upgrade from KioskConfig.git?ref=dev#<config>-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

# Build a system closure (any config name from flake.nix)
nix build .#nixosConfigurations.<name>.config.system.build.toplevel

# Build a bootable ISO
nix build .#nixosConfigurations.<name>.config.system.build.isoImage

# Deploy to a remote kiosk over SSH
nixos-rebuild switch --flake .#<name> --target-host root@<host>

# 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:
    sudo nix shell nixpkgs#nixos-facter -c nixos-facter -o facter-<model>.json
    
  3. Commit facter-<model>.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