Dev #8

Merged
NeilClack merged 16 commits from dev into main 2026-08-29 02:01:45 +00:00
3 changed files with 119 additions and 2 deletions
Showing only changes of commit d661162676 - Show all commits
+10 -2
View File
@@ -1,7 +1,15 @@
{ pkgs, radiantwave, upgradeFlakeRef, radiantwavePlymouth, ... }:
{ config, pkgs, radiantwave, upgradeFlakeRef, radiantwavePlymouth, ... }:
let
radiantApp = radiantwave.packages.${pkgs.system}.default;
# When the live-updater module is enabled (currently dev variants only),
# RadiantWave launches through the mutable /var/lib/radiantwave/current
# pointer so it can be swapped without a full nixos-rebuild. Otherwise it
# launches straight from the immutable system closure as before.
launchBin =
if config.services.radiantwaveUpdater.enable or false
then "/var/lib/radiantwave/current/bin/radiantwave"
else "/run/current-system/sw/bin/radiantwave";
myKey = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL4qWNZnYU5JaqR9c2qh6oFZktzVNBOx42PfDaGofCL6 cnclack@pm.me macbook" ];
in
{
@@ -159,7 +167,7 @@ in
# Release the splash screen right before the compositor takes over the display
sudo -n plymouth quit --wait || true
exec dbus-run-session cage -- /run/current-system/sw/bin/radiantwave -d -s > /tmp/kiosk.log 2>&1
exec dbus-run-session cage -- ${launchBin} -d -s > /tmp/kiosk.log 2>&1
fi
'';
+24
View File
@@ -55,6 +55,18 @@
revision = self.rev or self.dirtyRev or null;
# Live app-update side channel, dev-only for now. The manifest is
# served by the fileserver; closures are fetched (never built) from the
# dev Attic cache. Promotes to prod once validated.
radiantwaveDevUpdaterModule = { baseline }: {
services.radiantwaveUpdater = {
enable = true;
manifestUrl = "https://files.radiantwavetech.com/radiantwave-dev/manifest.json";
atticUrl = "https://attic.radiantwavetech.com/radiantwave-dev";
baselinePackage = baseline;
};
};
mkKioskSystem = {
system,
radiantwave,
@@ -79,6 +91,7 @@
system.configurationRevision = revision;
}
./configuration.nix
./radiantwave-updater.nix
disko.nixosModules.disko
diskModule
nixos-facter-modules.nixosModules.facter
@@ -116,6 +129,7 @@
];
})
./configuration.nix
./radiantwave-updater.nix
radiantwave.nixosModules.default
{
networking.hostName = hostName;
@@ -194,6 +208,9 @@
hostName = "radiantwavekiosk-dev";
diskModule = ./disk-config.nix;
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-dev";
extraModules = [
(radiantwaveDevUpdaterModule { baseline = radiantwave-dev.packages.x86_64-linux.default; })
];
};
radiantwavekiosk-commercial = mkKioskSystem {
system = "x86_64-linux";
@@ -208,6 +225,9 @@
hostName = "radiantwavekiosk-commercial-dev";
diskModule = ./commercial-disk-config.nix;
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-commercial-dev";
extraModules = [
(radiantwaveDevUpdaterModule { baseline = radiantwave-dev.packages.x86_64-linux.default; })
];
};
# Rotated screen for android-style displays.
radiantwavekiosk-android = mkKioskSystem {
@@ -228,6 +248,7 @@
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-android-dev";
extraModules = [
./rotated_display.nix
(radiantwaveDevUpdaterModule { baseline = radiantwave-dev.packages.x86_64-linux.default; })
];
};
# Raspberry Pi 5.
@@ -240,6 +261,9 @@
radiantwave = radiantwave-dev;
hostName = "radiantwavekiosk-rpi-dev";
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-rpi-dev";
extraModules = [
(radiantwaveDevUpdaterModule { baseline = radiantwave-dev.packages.aarch64-linux.default; })
];
};
# === USB Images ===
+85
View File
@@ -0,0 +1,85 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.radiantwaveUpdater;
in
{
options.services.radiantwaveUpdater = {
enable = lib.mkEnableOption "live RadiantWave app updates via a polled manifest";
manifestUrl = lib.mkOption {
type = lib.types.str;
description = "HTTP(S) URL of the JSON manifest announcing the current app store path.";
};
atticUrl = lib.mkOption {
type = lib.types.str;
description = "Attic cache URL to fetch the app closure from (fetch-only, never builds).";
};
baselinePackage = lib.mkOption {
type = lib.types.package;
description = "Copy of RadiantWave baked into the system closure, used to seed the runtime pointer before the first update.";
};
};
config = lib.mkIf cfg.enable {
# Runtime pointer the login shell launches RadiantWave from. Seeded on
# first boot to the baseline copy already baked into the system closure
# (so the ISO carries it with no duplication); the updater service later
# re-points it atomically to newer closures fetched from Attic.
systemd.tmpfiles.rules = [
"L /var/lib/radiantwave/current - - - - ${cfg.baselinePackage.outPath}"
];
systemd.services.radiantwave-updater = {
description = "Poll the RadiantWave manifest and swap the live app pointer";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
set -u
NEW_PATH=$(${pkgs.curl}/bin/curl -fsSL "${cfg.manifestUrl}" \
| ${pkgs.jq}/bin/jq -er .storePath) || {
echo "radiantwave-updater: failed to fetch/parse manifest from ${cfg.manifestUrl}"
exit 0
}
CURRENT=$(${pkgs.coreutils}/bin/readlink /var/lib/radiantwave/current 2>/dev/null || true)
if [ -z "$NEW_PATH" ] || [ "$NEW_PATH" = "$CURRENT" ]; then
echo "radiantwave-updater: already current (''${CURRENT})"
exit 0
fi
# Fetch the closure from the signed Attic cache only. This never
# builds from source; it fails outright if the path isn't there.
echo "radiantwave-updater: acquiring ''${NEW_PATH}"
${pkgs.nix}/bin/nix copy --from "${cfg.atticUrl}" "$NEW_PATH" || {
echo "radiantwave-updater: nix copy failed for ''${NEW_PATH}"
exit 1
}
# Atomic swap: the app never observes a half-updated pointer.
${pkgs.coreutils}/bin/ln -sfn "$NEW_PATH" /var/lib/radiantwave/current.tmp
${pkgs.coreutils}/bin/mv -T /var/lib/radiantwave/current.tmp /var/lib/radiantwave/current
echo "radiantwave-updater: swapped ''${CURRENT} -> ''${NEW_PATH}"
'';
};
systemd.timers.radiantwave-updater = {
description = "Check for RadiantWave app updates";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "2min";
OnUnitActiveSec = "2min";
Persistent = true;
Unit = "radiantwave-updater.service";
};
};
};
}