Dev #8
@@ -22,7 +22,7 @@ jobs:
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.dev-iso.config.system.build.isoImage
|
||||
nix build -L --impure .#nixosConfigurations.kiosk-iso.config.system.build.isoImage
|
||||
- name: Rename dev kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.android-dev-iso.config.system.build.isoImage
|
||||
nix build -L --impure .#nixosConfigurations.android-iso.config.system.build.isoImage
|
||||
- name: Rename dev android ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.commercial-dev-iso.config.system.build.isoImage
|
||||
nix build -L --impure .#nixosConfigurations.commercial-iso.config.system.build.isoImage
|
||||
- name: Rename dev commercial ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
|
||||
@@ -8,10 +8,12 @@ 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:
|
||||
Two branches — `main` (prod) and `dev`. There are **no `-dev` configs**: each hardware target has exactly one config, and the branch selects its channel via the single `channel` block at the top of `flake.nix`:
|
||||
|
||||
- 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`.
|
||||
- `main`: `channel.appInput = radiantwave` (main), `atticRepo = "radiantwave"`, `gitRef = ""` (default branch).
|
||||
- `dev`: `channel.appInput = radiantwave-dev`, `atticRepo = "radiantwave-dev"`, `gitRef = "?ref=dev"`.
|
||||
|
||||
Everything downstream (the configs, ISOs, updater module, autoUpgrade refs) reads from `channel`, so a `dev`→`main` merge carries your changes automatically — no copying between sibling configs. To flip a channel, change only those three `channel` values. When merging, reconcile just this one block.
|
||||
|
||||
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.
|
||||
|
||||
@@ -36,16 +38,16 @@ nix eval .#nixosConfigurations --apply builtins.attrNames
|
||||
|
||||
## Config variants
|
||||
|
||||
One config per hardware target. Dev/prod is the branch, not the config — see `channel` in `flake.nix`:
|
||||
|
||||
| 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) |
|
||||
|
||||
On the `dev` branch, the same four configs use `radiantwave-dev` and track `?ref=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.
|
||||
|
||||
@@ -56,11 +58,10 @@ Each ISO installs exactly one closure using that closure's disk layout (`mkIso`
|
||||
| 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 |
|
||||
|
||||
These same names build **dev-flavored** images when the flake is checked out on the `dev` branch (the channel block selects the dev app, attic repo, and upgrade ref), so there are no separate `-dev` ISOs.
|
||||
|
||||
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.
|
||||
|
||||
@@ -91,18 +92,19 @@ Regenerate when major hardware changes, not on a schedule — reports are snapsh
|
||||
|
||||
- **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).
|
||||
- **The `channel` block is the dev/prod toggle** in `flake.nix` — `appInput`, `atticRepo`, `gitRef`. When merging `dev`→`main`, keep this block's values for the target branch; only this block differs between branches.
|
||||
- **`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.
|
||||
- **Flake inputs**: `radiantwave` tracks main, `radiantwave-dev` tracks `?ref=dev`. The `channel` block picks which one the configs consume. 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
|
||||
- `flake.nix` — entry point: inputs, the `channel` dev/prod selector, 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
|
||||
- `zero-touch-installer.nix` — parameterized USB installer module used by all three 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
|
||||
|
||||
@@ -55,11 +55,29 @@
|
||||
|
||||
revision = self.rev or self.dirtyRev or null;
|
||||
|
||||
# DEV/PROD CHANNEL SELECTOR — the single block that differs between the
|
||||
# `main` and `dev` branches. Everything downstream (the four configs, the
|
||||
# ISOs, the updater module) is identical on both branches and pulls from
|
||||
# this channel, so a `dev`-to-`main` merge carries your changes with it
|
||||
# automatically. There are no more `-dev` sibling configs to copy.
|
||||
#
|
||||
# main: appInput = radiantwave (main), atticRepo = "radiantwave",
|
||||
# gitRef = "" (default branch)
|
||||
# dev: appInput = radiantwave-dev, atticRepo = "radiantwave-dev",
|
||||
# gitRef = "?ref=dev"
|
||||
#
|
||||
# To flip branches, change ONLY these three values (then push/merge).
|
||||
channel = {
|
||||
appInput = radiantwave; # main
|
||||
atticRepo = "radiantwave"; # main
|
||||
gitRef = ""; # main
|
||||
};
|
||||
|
||||
# Live app-update side channel. The manifest is served by the
|
||||
# fileserver; closures are fetched (never built) from the variant's
|
||||
# Attic cache. `repo` selects the channel — "radiantwave" (prod,
|
||||
# ?ref=main) or "radiantwave-dev" (dev, ?ref=dev). All variants follow
|
||||
# this same update procedure; only the channel differs.
|
||||
# fileserver; closures are fetched (never built) from the channel's
|
||||
# Attic cache. `repo` selects the channel — "radiantwave" (main) or
|
||||
# "radiantwave-dev" (dev). All variants follow this same update
|
||||
# procedure; only the channel differs.
|
||||
radiantwaveUpdaterModule = { repo, baseline }: {
|
||||
services.radiantwaveUpdater = {
|
||||
enable = true;
|
||||
@@ -183,99 +201,58 @@
|
||||
in
|
||||
{
|
||||
packages.x86_64-linux.radiantwavekiosk = self.nixosConfigurations.radiantwavekiosk.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-dev = self.nixosConfigurations.radiantwavekiosk-dev.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-commercial = self.nixosConfigurations.radiantwavekiosk-commercial.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-commercial-dev = self.nixosConfigurations.radiantwavekiosk-commercial-dev.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-android = self.nixosConfigurations.radiantwavekiosk-android.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-android-dev = self.nixosConfigurations.radiantwavekiosk-android-dev.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-rpi = self.nixosConfigurations.radiantwavekiosk-rpi.config.system.build.toplevel;
|
||||
packages.x86_64-linux.radiantwavekiosk-rpi-dev = self.nixosConfigurations.radiantwavekiosk-rpi-dev.config.system.build.toplevel;
|
||||
|
||||
# Kiosk systems.
|
||||
# Kiosk systems — one per hardware target, no dev/prod siblings.
|
||||
#
|
||||
# Production variants consume the `radiantwave` input (?ref=main);
|
||||
# `-dev` variants consume `radiantwave-dev` (?ref=dev). All variants
|
||||
# run the same live-app updater against their channel's Attic repo and
|
||||
# manifest, and track this repo's matching branch via autoUpgrade.
|
||||
# Every config consumes the channel selected at the top of this file
|
||||
# (see `channel`): the RadiantWave app input, the Attic repo/manifest
|
||||
# it fetches live updates from, and the KioskConfig git ref it
|
||||
# auto-upgrades from. On `main` the channel is prod; on `dev` it is the
|
||||
# dev channel. Because there is exactly one config per hardware type,
|
||||
# changes made on `dev` reach prod via a plain merge — no copying.
|
||||
nixosConfigurations = {
|
||||
radiantwavekiosk = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
radiantwave = channel.appInput;
|
||||
hostName = "radiantwavekiosk";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git${channel.gitRef}#radiantwavekiosk";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave"; baseline = radiantwave.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
radiantwavekiosk-dev = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave-dev;
|
||||
hostName = "radiantwavekiosk-dev";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-dev";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave-dev"; baseline = radiantwave-dev.packages.x86_64-linux.default; })
|
||||
(radiantwaveUpdaterModule { repo = channel.atticRepo; baseline = channel.appInput.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
radiantwavekiosk-commercial = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
radiantwave = channel.appInput;
|
||||
hostName = "radiantwavekiosk-commercial";
|
||||
diskModule = ./commercial-disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-commercial";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git${channel.gitRef}#radiantwavekiosk-commercial";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave"; baseline = radiantwave.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
radiantwavekiosk-commercial-dev = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave-dev;
|
||||
hostName = "radiantwavekiosk-commercial-dev";
|
||||
diskModule = ./commercial-disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-commercial-dev";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave-dev"; baseline = radiantwave-dev.packages.x86_64-linux.default; })
|
||||
(radiantwaveUpdaterModule { repo = channel.atticRepo; baseline = channel.appInput.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
# Rotated screen for android-style displays.
|
||||
radiantwavekiosk-android = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
radiantwave = channel.appInput;
|
||||
hostName = "radiantwavekiosk-android";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-android";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git${channel.gitRef}#radiantwavekiosk-android";
|
||||
extraModules = [
|
||||
./rotated_display.nix
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave"; baseline = radiantwave.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
radiantwavekiosk-android-dev = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave-dev;
|
||||
hostName = "radiantwavekiosk-android-dev";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-android-dev";
|
||||
extraModules = [
|
||||
./rotated_display.nix
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave-dev"; baseline = radiantwave-dev.packages.x86_64-linux.default; })
|
||||
(radiantwaveUpdaterModule { repo = channel.atticRepo; baseline = channel.appInput.packages.x86_64-linux.default; })
|
||||
];
|
||||
};
|
||||
# Raspberry Pi 5.
|
||||
radiantwavekiosk-rpi = mkRpiKioskSystem {
|
||||
radiantwave = radiantwave;
|
||||
radiantwave = channel.appInput;
|
||||
hostName = "radiantwavekiosk-rpi";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-rpi";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git${channel.gitRef}#radiantwavekiosk-rpi";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave"; baseline = radiantwave.packages.aarch64-linux.default; })
|
||||
];
|
||||
};
|
||||
radiantwavekiosk-rpi-dev = mkRpiKioskSystem {
|
||||
radiantwave = radiantwave-dev;
|
||||
hostName = "radiantwavekiosk-rpi-dev";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-rpi-dev";
|
||||
extraModules = [
|
||||
(radiantwaveUpdaterModule { repo = "radiantwave-dev"; baseline = radiantwave-dev.packages.aarch64-linux.default; })
|
||||
(radiantwaveUpdaterModule { repo = channel.atticRepo; baseline = channel.appInput.packages.aarch64-linux.default; })
|
||||
];
|
||||
};
|
||||
|
||||
@@ -283,6 +260,10 @@
|
||||
# Each ISO installs exactly the named system closure using that
|
||||
# system's disk layout. NVMe layouts pair with ./disk-config.nix,
|
||||
# SATA with ./commercial-disk-config.nix — don't cross them.
|
||||
# The same names build dev-flavored images when the flake is checked
|
||||
# out on the `dev` branch (the channel block above selects the dev
|
||||
# app, attic repo, and upgrade ref), so there are no separate -dev
|
||||
# ISOs.
|
||||
kiosk-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk";
|
||||
diskModule = ./disk-config.nix;
|
||||
@@ -295,18 +276,6 @@
|
||||
targetConfig = "radiantwavekiosk-android";
|
||||
diskModule = ./disk-config.nix;
|
||||
};
|
||||
dev-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk-dev";
|
||||
diskModule = ./disk-config.nix;
|
||||
};
|
||||
commercial-dev-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk-commercial-dev";
|
||||
diskModule = ./commercial-disk-config.nix;
|
||||
};
|
||||
android-dev-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk-android-dev";
|
||||
diskModule = ./disk-config.nix;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user