Compare commits
52
Commits
240be2540f
..
v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e22b466bb3 | ||
|
|
bd9146e641 | ||
|
|
9b0036b4da | ||
|
|
d26cec2a53 | ||
|
|
2e862c13a8 | ||
|
|
84ec13b1f9 | ||
|
|
588f0e4aa1 | ||
|
|
46384e6cf7 | ||
|
|
6951d35310 | ||
|
|
7778da3867 | ||
|
|
59e9f7ce29 | ||
|
|
3ec72c8479 | ||
|
|
20d91df9eb | ||
|
|
65a6b256f9 | ||
|
|
64b2a9cfc4 | ||
|
|
875f3da03d | ||
|
|
9965e30152 | ||
|
|
a01c3d5521 | ||
|
|
33c9ceefb0 | ||
|
|
c9743de7bb | ||
|
|
6ddf004e95 | ||
|
|
439e646170 | ||
|
|
f8cb1746af | ||
|
|
a4f4d17d6e | ||
|
|
e7a5ffa290 | ||
|
|
553b06ea92 | ||
|
|
8e8da490e4 | ||
|
|
75cce42de5 | ||
|
|
572ab76100 | ||
|
|
d37c794be4 | ||
|
|
b26081046e | ||
|
|
87367dab04 | ||
|
|
0a35c97379 | ||
|
|
2fb99175f7 | ||
|
|
02cde0fabb | ||
|
|
143119477f | ||
|
|
b584016db2 | ||
|
|
e09758a70e | ||
|
|
14463ad99b | ||
|
|
027d1a628f | ||
|
|
fb2f861258 | ||
|
|
974a610518 | ||
|
|
c71b5ebc84 | ||
|
|
6656c44de4 | ||
|
|
2788d27fdc | ||
|
|
72a564c9ef | ||
|
|
2185792cf4 | ||
|
|
3b9c501aa8 | ||
|
|
2abdfa2b9b | ||
|
|
0cb1337f18 | ||
|
|
50176d8fd5 | ||
|
|
06c2a7cd0a |
@@ -1,18 +1,26 @@
|
||||
name: Build Dev ISO
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
|
||||
env:
|
||||
NIX_CONFIG: |
|
||||
extra-substituters = https://attic.radiantwavetech.com/radiantwave-dev
|
||||
extra-trusted-public-keys = radiantwave-dev:B8FhLu3MQ9JfeEIHIKNrKxnP+3akzzkqMbTZR4hRfj0=
|
||||
|
||||
jobs:
|
||||
update-and-build:
|
||||
build-dev-iso:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Clone Repository
|
||||
run: git clone --depth 1 --no-single-branch ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git .
|
||||
|
||||
- name: Update radiantwave-dev
|
||||
run: |
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix flake update radiantwave-dev
|
||||
- name: Checkout dev branch
|
||||
run: git checkout dev
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
@@ -31,6 +39,9 @@ jobs:
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Move old dev images to archive
|
||||
run: tools/archive-images.sh nclack@157.245.124.103 /mnt/infrastructure_data/files/images /mnt/infrastructure_data/files/images/archives 'radiantwave-kiosk-dev*'
|
||||
|
||||
- name: Copy kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" \
|
||||
@@ -38,13 +49,3 @@ jobs:
|
||||
|
||||
- name: Cleanup kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${KIOSK_ISO_FILENAME}"
|
||||
|
||||
- name: Commit updated flake.lock
|
||||
run: |
|
||||
git config user.email "ci@radiantwavetech.com"
|
||||
git config user.name "RadiantWave CI"
|
||||
git remote set-url origin https://oauth2:${{ secrets.GIT_TOKEN }}@gitea.radiantwavetech.com/RadiantWaveTech/kioskconfig.git
|
||||
|
||||
git add flake.lock
|
||||
git commit -m "chore: update radiantwave-dev to latest" || echo "Nothing to commit"
|
||||
git push
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NIX_CONFIG: |
|
||||
extra-substituters = https://attic.radiantwavetech.com/radiantwave
|
||||
extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA=
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone --depth 1 ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git .
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
|
||||
- name: Build android kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.android-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename android kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-android-iso-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "ANDROID_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
# - name: Move old android images to archive
|
||||
# run: |
|
||||
# ssh nclack@157.245.124.103 'mv /mnt/infrastructure_data/files/images/radiantwave-android-iso* /mnt/infrastructure_data/files/images/archives/'
|
||||
|
||||
- name: Copy android kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${ANDROID_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup android kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${ANDROID_ISO_FILENAME}"
|
||||
@@ -0,0 +1,43 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NIX_CONFIG: |
|
||||
extra-substituters = https://attic.radiantwavetech.com/radiantwave
|
||||
extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA=
|
||||
|
||||
jobs:
|
||||
build-commercial:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone --depth 1 ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git .
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
|
||||
- name: Build commercial kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.commercial-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename commercial kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-commercial-iso-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "COMMERCIAL_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
# - name: Move old commercial images to archive
|
||||
# run: |
|
||||
# ssh nclack@157.245.124.103 'mv /mnt/infrastructure_data/files/images/radiantwave-commercial-iso* /mnt/infrastructure_data/files/images/archives/'
|
||||
|
||||
- name: Copy commercial kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${COMMERCIAL_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup commercial kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${COMMERCIAL_ISO_FILENAME}"
|
||||
@@ -0,0 +1,43 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NIX_CONFIG: |
|
||||
extra-substituters = https://attic.radiantwavetech.com/radiantwave
|
||||
extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA=
|
||||
|
||||
jobs:
|
||||
build-kiosk:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone --depth 1 ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git .
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
|
||||
- name: Build kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.kiosk-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-home-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
# - name: Move old kiosk images to archive
|
||||
# run: |
|
||||
# ssh nclack@157.245.124.103 'mv /mnt/infrastructure_data/files/images/radiantwave-home* /mnt/infrastructure_data/files/images/archives/'
|
||||
|
||||
- name: Copy kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${KIOSK_ISO_FILENAME}"
|
||||
@@ -0,0 +1,42 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NIX_CONFIG: |
|
||||
extra-substituters = https://attic.radiantwavetech.com/radiantwave https://nixos-raspberrypi.cachix.org
|
||||
extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA= nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI=
|
||||
|
||||
jobs:
|
||||
build-rpi:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone --depth 1 ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git .
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
|
||||
- name: Build Raspberry Pi image
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.radiantwavekiosk-rpi.config.system.build.sdImage
|
||||
|
||||
- name: Rename Raspberry Pi image
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-rpi-${ISO_DATE}.img.zst"
|
||||
cp -L result/sd-image/*.img.zst "/home/user/radiantwave/${FILENAME}"
|
||||
echo "RPI_IMAGE_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Move old Raspberry Pi images to archive
|
||||
run: tools/archive-images.sh nclack@157.245.124.103 /mnt/infrastructure_data/files/images /mnt/infrastructure_data/files/images/archives 'radiantwave-rpi*'
|
||||
|
||||
- name: Copy Raspberry Pi image to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${RPI_IMAGE_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup Raspberry Pi image
|
||||
run: rm -f "/home/user/radiantwave/${RPI_IMAGE_FILENAME}"
|
||||
@@ -1,133 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-and-build:
|
||||
runs-on: build-server
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Update radiantwave
|
||||
run: |
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix flake update radiantwave
|
||||
|
||||
- name: Prepare output directory
|
||||
run: mkdir -p /home/user/radiantwave
|
||||
|
||||
# --- Kiosk ISO ---
|
||||
- name: Build kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.kiosk-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-iso-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Copy kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${KIOSK_ISO_FILENAME}"
|
||||
|
||||
# --- Android Kiosk ISO ---
|
||||
- name: Build android kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.android-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename android kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-android-iso-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "ANDROID_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Copy android kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${ANDROID_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup android kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${ANDROID_ISO_FILENAME}"
|
||||
|
||||
# --- Commercial Kiosk ISO ---
|
||||
- name: Build commercial kiosk ISO
|
||||
run: |
|
||||
export NIXPKGS_ALLOW_UNFREE=1
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
nix build -L --impure .#nixosConfigurations.commercial-iso.config.system.build.isoImage
|
||||
|
||||
- name: Rename commercial kiosk ISO
|
||||
run: |
|
||||
ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
FILENAME="radiantwave-commercial-iso-${ISO_DATE}.iso"
|
||||
cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}"
|
||||
echo "COMMERCIAL_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Copy commercial kiosk ISO to fileserver
|
||||
run: |
|
||||
scp "/home/user/radiantwave/${COMMERCIAL_ISO_FILENAME}" \
|
||||
radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
|
||||
- name: Cleanup commercial kiosk ISO
|
||||
run: rm -f "/home/user/radiantwave/${COMMERCIAL_ISO_FILENAME}"
|
||||
|
||||
# --- Raspberry Pi image (disabled for speed, for now) ---
|
||||
# - name: Build Raspberry Pi image
|
||||
# run: |
|
||||
# export NIXPKGS_ALLOW_UNFREE=1
|
||||
# . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
# nix build -L --impure .#nixosConfigurations.radiantwavekiosk-rpi.config.system.build.sdImage
|
||||
#
|
||||
# - name: Rename Raspberry Pi image
|
||||
# run: |
|
||||
# ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
# FILENAME="radiantwave-rpi-${ISO_DATE}.img.zst"
|
||||
# cp -L result/sd-image/*.img.zst "/home/user/radiantwave/${FILENAME}"
|
||||
# echo "RPI_IMAGE_FILENAME=${FILENAME}" >> "$GITHUB_ENV"
|
||||
#
|
||||
# - name: Copy Raspberry Pi image to fileserver
|
||||
# run: |
|
||||
# scp "/home/user/radiantwave/${RPI_IMAGE_FILENAME}" \
|
||||
# radiantwave-infra:/mnt/infrastructure_data/files/images/
|
||||
#
|
||||
# - name: Cleanup Raspberry Pi image
|
||||
# run: rm -f "/home/user/radiantwave/${RPI_IMAGE_FILENAME}"
|
||||
|
||||
- name: Commit updated flake.lock
|
||||
run: |
|
||||
git config user.email "ci@radiantwavetech.com"
|
||||
git config user.name "RadiantWave CI"
|
||||
git remote set-url origin https://oauth2:${{ secrets.GIT_TOKEN }}@gitea.radiantwavetech.com/RadiantWaveTech/kioskconfig.git
|
||||
|
||||
git add flake.lock
|
||||
git commit -m "chore: update radiantwave-dev to latest" || echo "Nothing to commit"
|
||||
git push
|
||||
|
||||
# - name: Notify
|
||||
# if: always()
|
||||
# uses: https://github.com/dawidd6/action-send-mail@v3
|
||||
# with:
|
||||
# server_address: smtp.gmail.com
|
||||
# server_port: 587
|
||||
# username: ${{ secrets.MAIL_USERNAME }}
|
||||
# password: ${{ secrets.MAIL_PASSWORD }}
|
||||
# subject: "${{ job.status == 'success' && '✅' || '❌' }} KioskConfig main build ${{ job.status }}"
|
||||
# to: nclack@radiantwavetech.com
|
||||
# from: ci@radiantwavetech.com
|
||||
# body: "KioskConfig main build ${{ job.status }} — radiantwave updated and artifacts copied."
|
||||
@@ -2,10 +2,19 @@
|
||||
|
||||
## 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 input (from gitea.radiantwavetech.com).
|
||||
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
|
||||
|
||||
```bash
|
||||
@@ -18,7 +27,7 @@ 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
|
||||
# Push build result to Attic cache (not currently wired into any config)
|
||||
attic push kiosk ./result
|
||||
|
||||
# Evaluate available config names
|
||||
@@ -27,47 +36,79 @@ nix eval .#nixosConfigurations --apply builtins.attrNames
|
||||
|
||||
## Config variants
|
||||
|
||||
| Name | Target hardware | Disk device | Notes |
|
||||
| Name | Target hardware | Disk device | App input |
|
||||
|---|---|---|---|
|
||||
| `radiantwavekiosk` | Intel NUC 14 (NVMe) | `/dev/nvme0n1` | Production, uses `radiantwave` main |
|
||||
| `radiantwavekiosk-dev` | Intel NUC 14 (NVMe) | `/dev/nvme0n1` | Dev, uses `radiantwave-dev` ref |
|
||||
| `radiantwavekiosk-commercial` | Commercial HW (SATA) | `/dev/sda` | Production |
|
||||
| `radiantwavekiosk-commercial-dev` | Commercial HW (SATA) | `/dev/sda` | Dev |
|
||||
| `radiantwavekiosk-android` | Intel NUC 14 | `/dev/nvme0n1` | + rotated display (portrait) |
|
||||
| `radiantwavekiosk-rpi` | Raspberry Pi 5 | — | Uses `nixos-raspberrypi` |
|
||||
| `radiantwavekiosk-rpi-dev` | Raspberry Pi 5 | — | Dev, uses `radiantwave-dev` |
|
||||
| `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) |
|
||||
|
||||
ISOs: `usb-iso`, `commercial-usb-iso`, `android-iso`, `dev-iso` — each bakes in the corresponding system closure for zero-touch install.
|
||||
Every variant sets its own `networking.hostName` (same as the config name) and `system.configurationRevision`, so `tools/find_systems.zsh` can identify fleet members.
|
||||
|
||||
## Branching model
|
||||
### USB images (zero-touch installers)
|
||||
|
||||
Single branch (`main`). Production vs. dev split is at the **flake input** level (`radiantwave` vs `radiantwave-dev`), not at the branch level.
|
||||
Each ISO installs exactly one closure using that closure's disk layout (`mkIso` in `flake.nix` derives both from the target config name):
|
||||
|
||||
## CI (Forgejo)
|
||||
| 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 |
|
||||
|
||||
`.forgejo/workflows/build-dev.yml` — triggered by `repository_dispatch` (`radiantwave-dev-built`) from the RadiantWave repo. Updates `radiantwave-dev` input, builds dev closure + ISO, commits updated `flake.lock`. Runs on `neils-server-runner`.
|
||||
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-<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`. Don't mix them up.
|
||||
- **ISO configs reference specific system closures**: `iso-config.nix` hardcodes `radiantwavekiosk`, `dev-iso.nix` hardcodes `radiantwavekiosk-dev`, `commercial-iso-config.nix` hardcodes `radiantwavekiosk-commercial`. Changing a config name in `flake.nix` requires updating the corresponding ISO config.
|
||||
- **Attic cache token**: ISO configs embed a JWT token for Attic in `/etc/nix/netrc`. If builds fail with auth errors, the token may have expired (expiry in the JWT payload).
|
||||
- **`rotated_display.nix` uses `mkForce`** on `loginShellInit` — it replaces the entire kiosk startup script from `configuration.nix`, don't edit both.
|
||||
- **SOPS**: `.sops.yaml` configures age-based encryption for `secrets.yaml`. You'll need the private key matching `age1t2wpzv...` to decrypt.
|
||||
- **Flake inputs**: `radiantwave` tracks main, `radiantwave-dev` tracks `?ref=dev`. Updating them independently is intentional.
|
||||
- **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` — all system definitions, entry point
|
||||
- `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)
|
||||
- `iso-config.nix` — production ISO + zero-touch installer
|
||||
- `dev-iso.nix` — dev ISO + zero-touch installer
|
||||
- `commercial-iso-config.nix` — commercial ISO + zero-touch installer
|
||||
- `rotated_display.nix` — portrait display override for Android variant
|
||||
- `facter.json` — hardware facter report (NUC 14)
|
||||
- `14rvk.json`, `pn54.json` — additional hardware facter reports
|
||||
- `assets/` — logo and splash image
|
||||
- `plymouth-theme/` — boot splash theme
|
||||
- `commands.md` — quick-reference for build/deploy commands
|
||||
- `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
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
# DRM/KMS Direct Mode — Deferred to Post-Launch
|
||||
|
||||
**Status:** Deferred (too much risk before launch)
|
||||
**Created:** 2026-08-17
|
||||
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Remove Cage (Wayland compositor) from -dev kiosk variants and run RadiantWave
|
||||
directly on DRM/KMS via SDL3's built-in `SDL_VIDEODRIVER=drm` backend. This
|
||||
simplifies the stack, removes compositor overhead, and is better suited for
|
||||
embedded/hardware kiosks.
|
||||
|
||||
**Decision:** Deferring until after the current launch. Cage works, and the
|
||||
transition touches every variant's boot pipeline.
|
||||
|
||||
---
|
||||
|
||||
## What Cage Currently Provides
|
||||
|
||||
| Feature | How Cage Does It | DRM/KMS Replacement |
|
||||
|---------|------------------|---------------------|
|
||||
| Display mode setting | Opens `/dev/dri/card*` via libseat, selects connector/CRTC/mode | SDL3 DRM backend opens DRM devices directly |
|
||||
| Fullscreen surface | Creates Wayland surface, manages lifecycle | SDL3 creates DRM framebuffer surface |
|
||||
| Page flipping / VSync | Handles `drmHandlePageFlip()` | SDL3 DRM backend handles page flip |
|
||||
| Input devices | Opens `/dev/input/*` via libseat, generates Wayland events | SDL3 DRM backend reads evdev directly |
|
||||
| Keyboard mapping | XKB keymap loading, key repeat | SDL3 handles keymap translation |
|
||||
| Seat management | Connects to seatd via libseat | Not needed — group permissions (`video`, `input`) suffice |
|
||||
|
||||
---
|
||||
|
||||
## What Stays Safe Without Cage
|
||||
|
||||
| Concern | Why It's Safe |
|
||||
|---------|---------------|
|
||||
| **Audio** | PipeWire/ALSA works independently of the compositor. App uses SDL3_mixer -> ALSA. Audio init service still runs before launch. |
|
||||
| **WiFi** | NetworkManager uses system bus (`sd_bus_open_system()` in `network_manager.cpp`). No session bus needed. `networkmanager` group handles D-Bus access. |
|
||||
| **Keyboard/input** | SDL3's DRM backend reads `/dev/input/*` evdev directly. `input` group grants access. |
|
||||
| **DRM/display** | SDL3's DRM backend opens `/dev/dri/card*` directly. `video` group grants access. |
|
||||
| **Plymouth** | `sudo -n plymouth quit --wait` still works — Plymouth runs as root on DRM/KMS. |
|
||||
| **Auto-login** | getty autologin still works on tty1. |
|
||||
| **Health check** | `pgrep -f '.radiantwave-unwrapped'` still works — no wrapper changes. |
|
||||
| **Backup service** | Runs as kiosk user, rsyncs `~/.local/radiantwave`. No compositor dependency. |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan — 4 Phases
|
||||
|
||||
All changes are in **kioskconfig only**. The radiantwave app needs no code
|
||||
changes — SDL3 handles DRM/KMS internally when `SDL_VIDEODRIVER=drm` is set.
|
||||
The NixOS system already provides Mesa/EGL/GBM via `hardware.graphics.enable = true`.
|
||||
|
||||
Only **-dev** variants are modified. Production configs stay on Cage.
|
||||
|
||||
### New module: `kiosk-drm.nix`
|
||||
|
||||
A NixOS module that overrides the Wayland/cage setup:
|
||||
|
||||
- `environment.systemPackages = mkForce [...]` — same list as `configuration.nix`
|
||||
but **without `pkgs.cage`**
|
||||
- `environment.loginShellInit = mkForce ''...` — same script but:
|
||||
- Sets `SDL_VIDEODRIVER=drm` instead of `wayland`
|
||||
- Removes `WLR_RENDERER`, `WLR_NO_HARDWARE_CURSORS`, `QT_QPA_PLATFORM`,
|
||||
`XDG_SESSION_TYPE`, `GODEBUG`
|
||||
- Launches `exec /run/current-system/sw/bin/radiantwave` directly
|
||||
(no `dbus-run-session cage --`)
|
||||
- Keeps: network wait, audio init, Plymouth quit
|
||||
- `services.seatd.enable = mkForce false` — nothing uses libseat anymore
|
||||
|
||||
---
|
||||
|
||||
### Phase 1: `radiantwavekiosk-dev` (Intel NUC)
|
||||
|
||||
**Files:**
|
||||
- Create `kiosk-drm.nix`
|
||||
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
|
||||
`radiantwavekiosk-dev`
|
||||
- `dev-iso.nix` already targets `radiantwavekiosk-dev` — no change needed
|
||||
|
||||
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-dev.config.system.build.toplevel`
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: `radiantwavekiosk-commercial-dev` (commercial HW)
|
||||
|
||||
**Files:**
|
||||
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
|
||||
`radiantwavekiosk-commercial-dev`
|
||||
- Create `commercial-dev-iso.nix` (same pattern as `dev-iso.nix`, targeting
|
||||
`radiantwavekiosk-commercial-dev`)
|
||||
- Add `commercial-dev-iso` config to `flake.nix`
|
||||
|
||||
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-commercial-dev.config.system.build.toplevel`
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: `radiantwavekiosk-android-dev` (rotated display)
|
||||
|
||||
**Files:**
|
||||
- Create `radiantwavekiosk-android-dev` in `flake.nix` (currently only
|
||||
production `radiantwavekiosk-android` exists)
|
||||
- Create `android-kiosk-drm.nix` — DRM/KMS mode + display rotation
|
||||
|
||||
**Challenge:** `rotated_display.nix` uses `wlr-randr` (Wayland tool) for
|
||||
90-degree rotation. Without Cage/Wayland, this won't work. Alternatives:
|
||||
- Option A: Use `modetest` from `libdrm` to set DRM rotation property
|
||||
- Option B: Handle rotation in the app (query display orientation, render rotated)
|
||||
- Option C: Kernel DRM rotation via modprobe params or udev rule
|
||||
|
||||
This is the hardest phase — needs investigation.
|
||||
|
||||
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-android-dev.config.system.build.toplevel`
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: `radiantwavekiosk-rpi-dev` (RPi 5)
|
||||
|
||||
**Files:**
|
||||
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
|
||||
`radiantwavekiosk-rpi-dev`
|
||||
- Modify `build-rpi.sh`: update to build `radiantwavekiosk-rpi-dev` instead of
|
||||
`radiantwavekiosk-rpi`
|
||||
|
||||
RPi 5 uses VC4/V3D GPU driver — `hardware.graphics.enable = true` +
|
||||
`nixos-raspberrypi.nixosModules.raspberry-pi-5.display-vc4` already handles this.
|
||||
|
||||
**Verify:** `./build-rpi.sh` (builds SD card image)
|
||||
|
||||
---
|
||||
|
||||
## Risks and Unknowns
|
||||
|
||||
1. **SDL3 DRM backend maturity** — Less commonly used than the Wayland backend.
|
||||
Needs testing on NUC (Intel i915) and RPi 5 (VC4/V3D) hardware.
|
||||
|
||||
2. **Android rotation** — `wlr-randr` won't work without Wayland. Needs an
|
||||
alternative rotation strategy.
|
||||
|
||||
3. **Input device permissions** — SDL3's DRM backend reads `/dev/input/*`
|
||||
directly. Need to verify `input` group is sufficient and udev rules don't
|
||||
block access.
|
||||
|
||||
4. **Multi-GPU/multi-output** — DRM/KMS needs to select the right connector.
|
||||
SDL3 handles this, but edge cases exist (e.g., multiple monitors).
|
||||
|
||||
5. **Plymouth -> app handoff** — Plymouth runs on DRM/KMS too. The handoff
|
||||
should work, but timing might differ without a Wayland compositor in between.
|
||||
|
||||
---
|
||||
|
||||
## radiantwave Repo — No Changes Needed
|
||||
|
||||
The app doesn't directly use DRM/KMS APIs. SDL3 handles the DRM backend
|
||||
internally when `SDL_VIDEODRIVER=drm` is set. The Nix package doesn't need
|
||||
changes — SDL3 dynamically loads DRM libraries at runtime.
|
||||
|
||||
The only change is the environment variable in the kiosk startup script
|
||||
(`SDL_VIDEODRIVER=drm` vs `wayland`), which lives in kioskconfig.
|
||||
@@ -0,0 +1,632 @@
|
||||
# RadiantWave Kiosk Update System Plan
|
||||
|
||||
**Goal**: Bulletproof automatic update system for RadiantWave kiosk
|
||||
**Deadline**: Production in 2 days
|
||||
**Architecture**: Manifest-based app updates + Flake lock system updates + systemd service supervision
|
||||
**Timezone**: UTC (all kiosks run in UTC)
|
||||
**Variants**: All variants (production + dev) auto-update
|
||||
**Notifications**: Logs only (no email/Slack)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This plan implements a three-part update system:
|
||||
|
||||
1. **Kiosk App Supervision**: Convert the kiosk app from exec'd login shell to a supervised systemd user service with automatic restart
|
||||
2. **RadiantWave App Updates**: Hourly manifest checks trigger updates via Attic binary cache
|
||||
3. **System Updates**: NixOS updates on boot and nightly at 8PM UTC
|
||||
|
||||
All updates show Plymouth splash during transition and auto-rollback on failure.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ BOOT SEQUENCE │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 1. Plymouth splash (held indefinitely) │
|
||||
│ 2. getty autologin as kiosk on tty1 │
|
||||
│ 3. loginShellInit runs: │
|
||||
│ a. Set environment variables │
|
||||
│ b. Wait for network (up to 10s) │
|
||||
│ c. Start radiantwave-audio-init user service │
|
||||
│ d. Start kiosk-app.service (systemd user service) │
|
||||
│ e. Quit Plymouth │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ KIOSK APP SERVICE │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ kiosk-app.service (systemd user service) │
|
||||
│ ├─ Runs: dbus-run-session cage -- radiantwave -d -s │
|
||||
│ ├─ Restart=always, RestartSec=5 │
|
||||
│ ├─ Logs to /tmp/kiosk.log │
|
||||
│ └─ On failure: auto-restart (3 attempts) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ UPDATE CHECKERS │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ radiantwave-update-checker.service (hourly) │
|
||||
│ ├─ Checks: https://attic.radiantwavetech.com/manifest.json │
|
||||
│ ├─ If new version: trigger radiantwave-upgrade.service │
|
||||
│ └─ Runs as: root (system service) │
|
||||
│ │
|
||||
│ system-update-checker.service (on boot + 8PM UTC) │
|
||||
│ ├─ Triggers: nixos-upgrade.service │
|
||||
│ └─ Runs as: root (system service) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ UPGRADE PROCESS │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ radiantwave-upgrade.service (triggered by update checker) │
|
||||
│ ├─ 1. Show Plymouth splash │
|
||||
│ ├─ 2. Stop kiosk-app.service │
|
||||
│ ├─ 3. Update flake.lock (git pull) │
|
||||
│ ├─ 4. Run nixos-rebuild switch │
|
||||
│ ├─ 5. Restart kiosk-app.service │
|
||||
│ ├─ 6. Quit Plymouth │
|
||||
│ └─ 7. Health check (if fails: auto-rollback) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. Kiosk App Systemd Service
|
||||
|
||||
**File**: `kiosk-app.nix` (new module)
|
||||
|
||||
**Purpose**: Supervise the cage/radiantwave process with automatic restart
|
||||
|
||||
**Key Configuration**:
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# System service (runs as root, starts user service)
|
||||
systemd.services.kiosk-app = {
|
||||
description = "RadiantWave Kiosk Application";
|
||||
after = [ "graphical.target" ];
|
||||
wantedBy = [ "graphical.target" ];
|
||||
|
||||
# Start the user service
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.systemd}/bin/systemctl --user start kiosk-app-session.service";
|
||||
ExecStop = "${pkgs.systemd}/bin/systemctl --user stop kiosk-app-session.service";
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
# User service (actual cage/radiantwave process)
|
||||
systemd.user.services.kiosk-app-session = {
|
||||
description = "RadiantWave Kiosk Session";
|
||||
after = [ "graphical-session.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.dbus}/bin/dbus-run-session ${pkgs.cage}/bin/cage -- ${config.radiantApp}/bin/radiantwave -d -s";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
|
||||
# Logging
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
|
||||
# Environment
|
||||
Environment = [
|
||||
"GODEBUG=cgocheck=0"
|
||||
"WAYLAND_DISPLAY=wayland-0"
|
||||
"XDG_RUNTIME_DIR=/run/user/1000"
|
||||
];
|
||||
};
|
||||
|
||||
# Restart policy
|
||||
unitConfig = {
|
||||
StartLimitIntervalSec = 60;
|
||||
StartLimitBurst = 3;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Changes to `configuration.nix`**:
|
||||
- Remove the `exec` line from `environment.loginShellInit`
|
||||
- Add `systemctl --user start kiosk-app-session.service` instead
|
||||
- Keep Plymouth quit after service start
|
||||
|
||||
**Updated `loginShellInit`**:
|
||||
```nix
|
||||
environment.loginShellInit = ''
|
||||
# ... existing env setup and network wait ...
|
||||
|
||||
# Start audio init
|
||||
systemctl --user start radiantwave-audio-init.service
|
||||
|
||||
# Start kiosk app service
|
||||
systemctl --user start kiosk-app-session.service
|
||||
|
||||
# Wait a moment for cage to start
|
||||
sleep 2
|
||||
|
||||
# Quit Plymouth
|
||||
sudo -n plymouth quit --wait
|
||||
|
||||
# Keep shell alive (don't exec)
|
||||
# The systemd service manages the kiosk app
|
||||
'';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Attic Cache Configuration
|
||||
|
||||
**File**: `attic-cache.nix` (new module)
|
||||
|
||||
**Purpose**: Configure Nix to use Attic as a binary cache
|
||||
|
||||
**Key Configuration**:
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Add Attic to trusted caches
|
||||
nix.settings = {
|
||||
trusted-caches = [
|
||||
"https://attic.radiantwavetech.com/radiantwave"
|
||||
];
|
||||
|
||||
# Extra substituters (for pulling)
|
||||
extra-substituters = [
|
||||
"https://attic.radiantwavetech.com/radiantwave"
|
||||
];
|
||||
|
||||
# Public keys (Attic uses Ed25519)
|
||||
trusted-public-keys = [
|
||||
"radiantwave:PLACEHOLDER_PUBLIC_KEY"
|
||||
];
|
||||
};
|
||||
|
||||
# Ensure nix can use the cache without authentication
|
||||
# (Attic is configured as public/open)
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: Replace `PLACEHOLDER_PUBLIC_KEY` with the actual Attic public key after server setup.
|
||||
|
||||
---
|
||||
|
||||
### 3. RadiantWave Update Checker
|
||||
|
||||
**File**: `radiantwave-update-checker.nix` (new module)
|
||||
|
||||
**Purpose**: Check Attic manifest hourly for new RadiantWave versions
|
||||
|
||||
**Key Configuration**:
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
systemd.services.radiantwave-update-checker = {
|
||||
description = "Check for RadiantWave updates";
|
||||
|
||||
# Run hourly
|
||||
startAt = "hourly";
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
||||
# Check manifest and trigger upgrade if needed
|
||||
ExecStart = pkgs.writeScript "check-radiantwave-update" ''
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
MANIFEST_URL="https://attic.radiantwavetech.com/manifest.json"
|
||||
CURRENT_VERSION_FILE="/etc/radiantwave-version"
|
||||
|
||||
# Fetch manifest
|
||||
MANIFEST=$(curl -sf "$MANIFEST_URL" || exit 0)
|
||||
|
||||
# Extract version
|
||||
NEW_VERSION=$(echo "$MANIFEST" | ${pkgs.jq}/bin/jq -r '.version')
|
||||
|
||||
# Get current version
|
||||
if [ -f "$CURRENT_VERSION_FILE" ]; then
|
||||
CURRENT_VERSION=$(cat "$CURRENT_VERSION_FILE")
|
||||
else
|
||||
CURRENT_VERSION="0.0.0"
|
||||
fi
|
||||
|
||||
# Compare versions
|
||||
if [ "$NEW_VERSION" != "$CURRENT_VERSION" ]; then
|
||||
echo "Update available: $CURRENT_VERSION -> $NEW_VERSION"
|
||||
# Trigger upgrade
|
||||
systemctl start radiantwave-upgrade.service
|
||||
else
|
||||
echo "Already up to date: $CURRENT_VERSION"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Upgrade service (triggered by checker)
|
||||
systemd.services.radiantwave-upgrade = {
|
||||
description = "Upgrade RadiantWave";
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
||||
# Show Plymouth during upgrade
|
||||
ExecStartPre = "${pkgs.plymouth}/bin/plymouth show-splash || true";
|
||||
|
||||
# Stop kiosk
|
||||
ExecStart = "${pkgs.systemd}/bin/systemctl stop kiosk-app.service";
|
||||
|
||||
# Update flake.lock and rebuild
|
||||
ExecStart = pkgs.writeScript "upgrade-radiantwave" ''
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Update flake.lock
|
||||
cd ${config.system.build.toplevel} # or git repo path
|
||||
git pull origin main
|
||||
|
||||
# Update radiantwave input
|
||||
nix flake update radiantwave
|
||||
|
||||
# Rebuild and switch
|
||||
nixos-rebuild switch --flake .#${config.networking.hostName}
|
||||
|
||||
# Update version file
|
||||
NEW_VERSION=$(curl -sf https://attic.radiantwavetech.com/manifest.json | ${pkgs.jq}/bin/jq -r '.version')
|
||||
echo "$NEW_VERSION" > /etc/radiantwave-version
|
||||
'';
|
||||
|
||||
# Restart kiosk
|
||||
ExecStart = "${pkgs.systemd}/bin/systemctl start kiosk-app.service";
|
||||
|
||||
# Quit Plymouth
|
||||
ExecStartPost = "${pkgs.plymouth}/bin/plymouth quit --wait || true";
|
||||
|
||||
# Rollback on failure
|
||||
FailureAction = "none"; # Handled by healthcheck
|
||||
|
||||
# Timeout
|
||||
TimeoutStartSec = 300; # 5 minutes for rebuild
|
||||
};
|
||||
|
||||
# Run after update checker
|
||||
after = [ "radiantwave-update-checker.service" ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. System Update Configuration
|
||||
|
||||
**File**: `system-updates.nix` (modify existing)
|
||||
|
||||
**Purpose**: Configure NixOS system updates on boot and nightly at 8PM UTC
|
||||
|
||||
**Changes to `configuration.nix`**:
|
||||
```nix
|
||||
# Replace existing system.autoUpgrade
|
||||
system.autoUpgrade = {
|
||||
enable = true;
|
||||
flake = upgradeFlakeRef; # e.g., "git+https://gitea...KioskConfig.git#radiantwavekiosk"
|
||||
|
||||
# Run on boot and nightly at 8PM UTC (kiosks are in UTC)
|
||||
dates = "20:00"; # 8PM UTC daily
|
||||
randomizedDelaySec = "10min"; # Avoid thundering herd
|
||||
|
||||
flags = [ "--refresh" "-L" ];
|
||||
operation = "switch";
|
||||
};
|
||||
```
|
||||
|
||||
**Note**: The existing health check service (`radiantwave-healthcheck`) already runs after `nixos-upgrade.service` and handles rollback. Keep this as-is.
|
||||
|
||||
---
|
||||
|
||||
### 5. Update Rollback Mechanism
|
||||
|
||||
**File**: `update-rollback.nix` (modify existing health check)
|
||||
|
||||
**Purpose**: Auto-rollback on failed updates
|
||||
|
||||
**Existing mechanism** (already in `configuration.nix`):
|
||||
```nix
|
||||
systemd.services.radiantwave-healthcheck = {
|
||||
description = "Health check after upgrade";
|
||||
after = [ "nixos-upgrade.service" ];
|
||||
wantedBy = [ "nixos-upgrade.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStartPre = "sleep 90"; # Wait for cage to start
|
||||
ExecStart = pkgs.writeScript "healthcheck" ''
|
||||
#!/bin/bash
|
||||
if ! pgrep -f ".radiantwave-unwrapped"; then
|
||||
echo "Health check failed, rolling back..."
|
||||
nixos-rebuild switch --rollback
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
**Enhancement**: Add version file tracking and logging:
|
||||
```nix
|
||||
ExecStart = pkgs.writeScript "healthcheck" ''
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
LOG_FILE="/var/log/radiantwave-healthcheck.log"
|
||||
|
||||
echo "$(date): Starting health check" >> "$LOG_FILE"
|
||||
|
||||
# Wait for cage to start
|
||||
sleep 10
|
||||
|
||||
# Check if radiantwave is running
|
||||
if pgrep -f ".radiantwave-unwrapped" > /dev/null; then
|
||||
echo "$(date): Health check passed" >> "$LOG_FILE"
|
||||
# Update version file on success
|
||||
if [ -f "/tmp/pending-version" ]; then
|
||||
cp /tmp/pending-version /etc/radiantwave-version
|
||||
fi
|
||||
else
|
||||
echo "$(date): Health check FAILED, rolling back..." >> "$LOG_FILE"
|
||||
nixos-rebuild switch --rollback 2>> "$LOG_FILE"
|
||||
echo "$(date): Rollback complete" >> "$LOG_FILE"
|
||||
fi
|
||||
'';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. CI Changes to Push to Attic
|
||||
|
||||
**File**: `.gitea/workflows/build-prod.yml` (modify)
|
||||
|
||||
**Purpose**: Push built closures to Attic cache
|
||||
|
||||
**Add to workflow**:
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# ... existing build steps ...
|
||||
|
||||
# Push to Attic
|
||||
- name: Push to Attic cache
|
||||
run: |
|
||||
# Install attic-client
|
||||
nix profile install github:zedant/attic#attic-client
|
||||
|
||||
# Login to Attic (token from secrets)
|
||||
attic login production https://attic.radiantwavetech.com production "${{ secrets.ATTIC_TOKEN }}"
|
||||
|
||||
# Push closures
|
||||
attic push production ./result-kiosk
|
||||
attic push production ./result-android
|
||||
attic push production ./result-commercial
|
||||
|
||||
# Update manifest
|
||||
- name: Update manifest
|
||||
run: |
|
||||
VERSION=$(date +%Y.%m.%d-%H%M)
|
||||
STORE_PATH=$(readlink -f ./result-kiosk)
|
||||
|
||||
# Create manifest
|
||||
cat > manifest.json << EOF
|
||||
{
|
||||
"version": "$VERSION",
|
||||
"storePath": "$STORE_PATH",
|
||||
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"commit": "${{ github.sha }}"
|
||||
}
|
||||
EOF
|
||||
|
||||
# Upload manifest to Attic or fileserver
|
||||
# (Attic doesn't support arbitrary file uploads, so use a fileserver or git)
|
||||
```
|
||||
|
||||
**Note**: Attic doesn't support arbitrary file uploads. Options for manifest:
|
||||
1. Host on a simple fileserver (nginx, S3, etc.)
|
||||
2. Commit to a git repo and serve via GitHub/Gitea Pages
|
||||
3. Use Attic's labels feature (if available)
|
||||
|
||||
---
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Attic Server Setup (User's Responsibility)
|
||||
- [ ] Set up Attic server at `attic.radiantwavetech.com`
|
||||
- [ ] Configure public/open access (no authentication)
|
||||
- [ ] Create cache named `radiantwave`
|
||||
- [ ] Note the public key for Nix configuration
|
||||
- [ ] Test pushing a closure: `attic push radiantwave /nix/store/...`
|
||||
|
||||
### Phase 2: Manifest Hosting (User's Responsibility)
|
||||
- [ ] Choose manifest hosting location (fileserver, git, S3)
|
||||
- [ ] Create initial manifest with current version
|
||||
- [ ] Ensure manifest is accessible via HTTPS
|
||||
|
||||
### Phase 3: Kiosk Configuration Changes
|
||||
- [ ] Create `kiosk-app.nix` module with systemd service
|
||||
- [ ] Create `attic-cache.nix` module for Attic configuration
|
||||
- [ ] Create `radiantwave-update-checker.nix` module
|
||||
- [ ] Modify `configuration.nix`:
|
||||
- Remove `exec` from `loginShellInit`
|
||||
- Add `systemctl --user start kiosk-app-session.service`
|
||||
- Update `system.autoUpgrade` schedule
|
||||
- [ ] Modify `rotated_display.nix` to match changes
|
||||
- [ ] Test locally with `nixos-rebuild build`
|
||||
|
||||
### Phase 4: CI Changes
|
||||
- [ ] Add Attic push step to `build-prod.yml`
|
||||
- [ ] Add manifest update step
|
||||
- [ ] Test CI pipeline with manual trigger
|
||||
|
||||
### Phase 5: Testing
|
||||
- [ ] Build ISO with changes
|
||||
- [ ] Test on VM or physical hardware
|
||||
- [ ] Verify kiosk starts automatically
|
||||
- [ ] Test manual update trigger
|
||||
- [ ] Test automatic update detection
|
||||
- [ ] Test rollback on failure
|
||||
- [ ] Test Plymouth splash during updates
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Kiosk App Service
|
||||
- [ ] Kiosk starts automatically on boot
|
||||
- [ ] Kiosk restarts if crashed (kill -9 radiantwave)
|
||||
- [ ] Logs appear in `/tmp/kiosk.log` and `journalctl`
|
||||
- [ ] Audio init completes before kiosk starts
|
||||
|
||||
### Update Detection
|
||||
- [ ] Manifest check runs hourly
|
||||
- [ ] System update check runs on boot
|
||||
- [ ] System update check runs at 8PM UTC
|
||||
- [ ] Checker logs show current vs available version
|
||||
|
||||
### Update Process
|
||||
- [ ] Plymouth splash shows during update
|
||||
- [ ] Kiosk stops before rebuild
|
||||
- [ ] Rebuild completes successfully
|
||||
- [ ] Kiosk restarts after rebuild
|
||||
- [ ] Plymouth quits after kiosk starts
|
||||
- [ ] Version file updates on success
|
||||
|
||||
### Rollback
|
||||
- [ ] Health check runs after upgrade
|
||||
- [ ] Rollback triggers if radiantwave not running
|
||||
- [ ] Rollback completes successfully
|
||||
- [ ] Logs show rollback reason
|
||||
|
||||
### Network Failure Handling
|
||||
- [ ] Update checker continues if manifest unreachable
|
||||
- [ ] Rebuild continues if Attic unreachable (uses local cache)
|
||||
- [ ] Kiosk restarts even if update fails
|
||||
|
||||
---
|
||||
|
||||
## File Map (New/Modified)
|
||||
|
||||
### New Files
|
||||
- `kiosk-app.nix` - Systemd service for kiosk app
|
||||
- `attic-cache.nix` - Attic binary cache configuration
|
||||
- `radiantwave-update-checker.nix` - Hourly update checker
|
||||
- `system-updates.nix` - System update schedule (or modify configuration.nix)
|
||||
|
||||
### Modified Files
|
||||
- `configuration.nix` - Remove exec, add service start, update autoUpgrade schedule
|
||||
- `rotated_display.nix` - Match loginShellInit changes
|
||||
- `.gitea/workflows/build-prod.yml` - Add Attic push step
|
||||
- `.gitea/workflows/build-dev.yml` - Add Attic push step (optional)
|
||||
|
||||
---
|
||||
|
||||
## Rollback Strategy
|
||||
|
||||
If the update system itself fails:
|
||||
|
||||
1. **Manual rollback**: SSH into kiosk, run `nixos-rebuild switch --rollback`
|
||||
2. **Boot previous generation**: Select previous generation in systemd-boot (if timeout enabled)
|
||||
3. **Reinstall from ISO**: Last resort, use zero-touch installer ISO
|
||||
|
||||
---
|
||||
|
||||
## Monitoring and Debugging
|
||||
|
||||
### Logs to Check
|
||||
- `/tmp/kiosk.log` - Kiosk app output
|
||||
- `journalctl -u kiosk-app.service` - Systemd service logs
|
||||
- `journalctl -u radiantwave-update-checker.service` - Update checker logs
|
||||
- `journalctl -u radiantwave-upgrade.service` - Upgrade process logs
|
||||
- `/var/log/radiantwave-healthcheck.log` - Health check results
|
||||
|
||||
### Manual Commands
|
||||
```bash
|
||||
# Check current version
|
||||
cat /etc/radiantwave-version
|
||||
|
||||
# Check manifest manually
|
||||
curl -sf https://attic.radiantwavetech.com/manifest.json | jq
|
||||
|
||||
# Trigger manual update
|
||||
systemctl start radiantwave-upgrade.service
|
||||
|
||||
# Check kiosk service status
|
||||
systemctl --user status kiosk-app-session.service
|
||||
|
||||
# View kiosk logs
|
||||
journalctl -u kiosk-app.service -f
|
||||
|
||||
# Manual rollback
|
||||
nixos-rebuild switch --rollback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| Attic server unavailable | Updates fail, kiosk continues running | Update checker continues hourly, kiosk unaffected |
|
||||
| Manifest corrupted | False update trigger | Version comparison logic, checksums |
|
||||
| Rebuild fails | Kiosk stays on old version | Automatic rollback via health check |
|
||||
| Kiosk crashes during update | Plymouth stays on screen | Timeout mechanisms, manual intervention |
|
||||
| Network partition | No updates possible | Kiosk continues on current version |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Kiosk starts automatically on boot (no manual intervention)
|
||||
- [ ] Kiosk restarts automatically if crashed
|
||||
- [ ] RadiantWave updates check every hour
|
||||
- [ ] System updates check on boot and 8PM UTC
|
||||
- [ ] Updates show Plymouth splash during transition
|
||||
- [ ] Failed updates auto-rollback within 2 minutes
|
||||
- [ ] All operations logged for debugging
|
||||
- [ ] Zero manual intervention required for routine updates
|
||||
|
||||
---
|
||||
|
||||
## Timeline
|
||||
|
||||
**Day 1 (Today)**:
|
||||
- [ ] Set up Attic server
|
||||
- [ ] Create manifest hosting
|
||||
- [ ] Implement kiosk-app.nix
|
||||
- [ ] Implement attic-cache.nix
|
||||
- [ ] Test kiosk service locally
|
||||
|
||||
**Day 2 (Tomorrow)**:
|
||||
- [ ] Implement update checker modules
|
||||
- [ ] Update CI workflows
|
||||
- [ ] Build test ISO
|
||||
- [ ] Test on hardware
|
||||
- [ ] Deploy to production
|
||||
|
||||
---
|
||||
|
||||
## Questions for Clarification
|
||||
|
||||
1. ~~Where will the manifest file be hosted?~~ → **Fileserver (nginx/Caddy)**
|
||||
2. ~~What timezone is the kiosk in?~~ → **UTC (all kiosks)**
|
||||
3. ~~Should dev variants also auto-update?~~ → **Yes, all variants**
|
||||
4. Do you want a manual "check for updates" button in the kiosk UI?
|
||||
5. ~~Should we notify admins of failed updates?~~ → **Logs only**
|
||||
@@ -1,128 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
let
|
||||
# TODO: Parameterize this to combine with iso-config.nix
|
||||
# Currently hardcoded to radiantwavekiosk-commercial; should accept target config as param
|
||||
targetSystem =
|
||||
self.nixosConfigurations.radiantwavekiosk-commercial.config.system.build.toplevel;
|
||||
|
||||
diskoScript =
|
||||
self.nixosConfigurations.radiantwavekiosk-commercial.config.system.build.diskoScript;
|
||||
in
|
||||
{
|
||||
nix.settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
];
|
||||
|
||||
flake-registry = "";
|
||||
};
|
||||
|
||||
nix.registry.nixpkgs = pkgs.lib.mkForce {
|
||||
to = {
|
||||
type = "path";
|
||||
path = "${inputs.nixpkgs}";
|
||||
};
|
||||
};
|
||||
|
||||
environment.variables.KIOSK_FLAKE = "${self}";
|
||||
|
||||
virtualisation.vmVariant = {
|
||||
virtualisation.memorySize = 8096;
|
||||
virtualisation.diskSize = 100000;
|
||||
virtualisation.cores = 4;
|
||||
virtualisation.qemu.options = [
|
||||
# "-nic none"
|
||||
];
|
||||
virtualisation.forwardPorts = [
|
||||
{ from = "host"; host.port = 2222; guest.port = 22; }
|
||||
];
|
||||
};
|
||||
|
||||
environment.etc."nix/netrc" = {
|
||||
text = ''
|
||||
password eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIwODgzODk2ODEsIm5iZiI6MTc3MjgxMzY4MSwic3ViIjoia2lvc2siLCJodHRwczovL2p3dC5hdHRpYy5ycy92MSI6eyJjYWNoZXMiOnsia2lvc2siOnsiciI6MX19fX0.N6Ktrmmu1LSy2PP8uNF25VHRP1dxPZJ4M0MR1kUpVi0
|
||||
'';
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
nix.extraOptions = ''
|
||||
netrc-file = /etc/nix/netrc
|
||||
'';
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
systemd.services.NetworkManager-wait-online.enable = false;
|
||||
|
||||
nix.settings.connect-timeout = 0;
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB4vXx7sOOVAyxdS/N1LEI+L8wYICf+gbzs6Kz7K8Je5 cnclack@pm.me:Thinkpad"
|
||||
];
|
||||
|
||||
systemd.services.zero-touch-install = {
|
||||
description = "Zero-Touch Kiosk Installation";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
wants = [ ];
|
||||
after = [ "systemd-udev-settle.service" ];
|
||||
|
||||
path = with pkgs; [
|
||||
nix
|
||||
git
|
||||
util-linux
|
||||
nixos-install-tools
|
||||
curl
|
||||
networkmanager
|
||||
mount
|
||||
umount
|
||||
disko
|
||||
];
|
||||
|
||||
environment = {
|
||||
NIX_PATH = "nixpkgs=${inputs.nixpkgs}";
|
||||
KIOSK_FLAKE = "${self}";
|
||||
DISKO_SCRIPT = "${diskoScript}";
|
||||
};
|
||||
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
|
||||
echo "Running disko script..."
|
||||
echo "Script: $DISKO_SCRIPT"
|
||||
|
||||
${diskoScript}
|
||||
|
||||
echo "Installing RadiantWave"
|
||||
echo "Closure Path: ${targetSystem}"
|
||||
|
||||
nixos-install \
|
||||
--system "${targetSystem}" \
|
||||
--no-root-passwd \
|
||||
--no-channel-copy
|
||||
|
||||
# Redirect to console and show completion message
|
||||
exec > /dev/tty1 2>&1
|
||||
echo ""
|
||||
echo "============================================="
|
||||
echo " Installation complete!"
|
||||
echo ""
|
||||
echo " Please remove the USB drive and reboot."
|
||||
echo "============================================="
|
||||
|
||||
# Wait indefinitely for user action
|
||||
sleep infinity
|
||||
''; };
|
||||
}
|
||||
+47
-30
@@ -55,14 +55,28 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
# Let the kiosk app apply pending updates by restarting its own TTY
|
||||
# session (re-autologin -> fresh cage + RadiantWave). Scoped to exactly
|
||||
# one unit and verb; everything else keeps stock (denied) policy.
|
||||
security.polkit.enable = true;
|
||||
environment.etc."polkit-1/rules.d/10-kiosk-getty.rules".text = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (subject.user !== "kiosk") return null;
|
||||
if (action.id !== "org.freedesktop.systemd1.manage-units") return null;
|
||||
var unit = action.lookup("unit");
|
||||
var verb = action.lookup("verb");
|
||||
if ((unit === "getty@tty1.service" || unit === "getty@tty1") && verb === "restart") {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
hardware.graphics.enable = true;
|
||||
|
||||
time.timeZone = "America/Chicago";
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
nix.settings.access-tokens = "gitea.radiantwavetech.com=ff524968d31acc5c4da350d0884a87264d0e8881";
|
||||
|
||||
system.autoUpgrade = {
|
||||
enable = true;
|
||||
flake = upgradeFlakeRef;
|
||||
@@ -71,10 +85,6 @@ in
|
||||
operation = "switch";
|
||||
};
|
||||
|
||||
system.activationScripts.cleanRadiantFiles = ''
|
||||
rm -rf /home/kiosk/.local/radiantwave/audio
|
||||
'';
|
||||
|
||||
# Virtual machine declaration
|
||||
virtualisation.vmVariant = {
|
||||
boot.loader.systemd-boot.enable = pkgs.lib.mkForce false;
|
||||
@@ -98,6 +108,14 @@ in
|
||||
# NixOS settings.
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
nix.settings.accept-flake-config = true;
|
||||
nix.settings.extra-substituters = [
|
||||
"https://attic.radiantwavetech.com/radiantwave"
|
||||
"https://attic.radiantwavetech.com/radiantwave-dev"
|
||||
];
|
||||
nix.settings.extra-trusted-public-keys = [
|
||||
"radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA="
|
||||
"radiantwave-dev:B8FhLu3MQ9JfeEIHIKNrKxnP+3akzzkqMbTZR4hRfj0="
|
||||
];
|
||||
system.stateVersion = "24.05";
|
||||
|
||||
############################################################
|
||||
@@ -110,7 +128,6 @@ in
|
||||
uid = 1000;
|
||||
extraGroups = ["audio" "video" "input" "networkmanager" "wheel" "seat"];
|
||||
openssh.authorizedKeys.keys = myKey;
|
||||
password = "Fuckp@ssw0rds";
|
||||
};
|
||||
|
||||
services.getty.autologinUser = "kiosk";
|
||||
@@ -240,30 +257,30 @@ in
|
||||
};
|
||||
|
||||
# --- Health check service: runs after nixos-upgrade ---
|
||||
systemd.services.radiantwave-healthcheck = {
|
||||
description = "Verify RadiantWave is running after upgrade, rollback if not";
|
||||
after = [ "nixos-upgrade.service" ];
|
||||
wantedBy = [ "nixos-upgrade.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
# Give cage time to start radiantwave after the switch
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/sleep 90";
|
||||
};
|
||||
script = ''
|
||||
# The installed `radiantwave` is a makeWrapper script that execs the real
|
||||
# binary (`.radiantwave-unwrapped`), so the process comm is not exactly
|
||||
# `radiantwave`; match the exec'd binary's command line instead.
|
||||
if ${pkgs.procps}/bin/pgrep -f '\.radiantwave-unwrapped' > /dev/null; then
|
||||
echo "RadiantWave is running, upgrade successful"
|
||||
exit 0
|
||||
fi
|
||||
# systemd.services.radiantwave-healthcheck = {
|
||||
# description = "Verify RadiantWave is running after upgrade, rollback if not";
|
||||
# after = [ "nixos-upgrade.service" ];
|
||||
# wantedBy = [ "nixos-upgrade.service" ];
|
||||
# serviceConfig = {
|
||||
# Type = "oneshot";
|
||||
# # Give cage time to start radiantwave after the switch
|
||||
# ExecStartPre = "${pkgs.coreutils}/bin/sleep 90";
|
||||
# };
|
||||
# script = ''
|
||||
# # The installed `radiantwave` is a makeWrapper script that execs the real
|
||||
# # binary (`.radiantwave-unwrapped`), so the process comm is not exactly
|
||||
# # `radiantwave`; match the exec'd binary's command line instead.
|
||||
# if ${pkgs.procps}/bin/pgrep -f '\.radiantwave-unwrapped' > /dev/null; then
|
||||
# echo "RadiantWave is running, upgrade successful"
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
echo "RadiantWave not found after upgrade, rolling back..."
|
||||
# echo "RadiantWave not found after upgrade, rolling back..."
|
||||
|
||||
# Roll back to previous NixOS generation
|
||||
/run/current-system/sw/bin/nixos-rebuild switch --rollback
|
||||
# # Roll back to previous NixOS generation
|
||||
# /run/current-system/sw/bin/nixos-rebuild switch --rollback
|
||||
|
||||
echo "Rollback completed at $(date)"
|
||||
'';
|
||||
};
|
||||
# echo "Rollback completed at $(date)"
|
||||
# '';
|
||||
# };
|
||||
}
|
||||
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
let
|
||||
targetSystem =
|
||||
self.nixosConfigurations.radiantwavekiosk-dev.config.system.build.toplevel;
|
||||
|
||||
diskoScript =
|
||||
self.nixosConfigurations.radiantwavekiosk-dev.config.system.build.diskoScript;
|
||||
in
|
||||
{
|
||||
############################################################
|
||||
# System configuration
|
||||
############################################################
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
];
|
||||
|
||||
flake-registry = "";
|
||||
|
||||
connect-timeout = 0;
|
||||
};
|
||||
|
||||
nix.registry.nixpkgs = pkgs.lib.mkForce {
|
||||
to = {
|
||||
type = "path";
|
||||
path = "${inputs.nixpkgs}";
|
||||
};
|
||||
};
|
||||
|
||||
nix.extraOptions = ''
|
||||
netrc-file = /etc/nix/netrc
|
||||
'';
|
||||
|
||||
environment.variables.KIOSK_FLAKE = "${self}";
|
||||
|
||||
environment.etc."nix/netrc" = {
|
||||
text = ''
|
||||
password eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIwODgzODk2ODEsIm5iZiI6MTc3MjgxMzY4MSwic3ViIjoia2lvc2siLCJodHRwczovL2p3dC5hdHRpYy5ycy92MSI6eyJjYWNoZXMiOnsia2lvc2siOnsiciI6MX19fX0.N6Ktrmmu1LSy2PP8uNF25VHRP1dxPZJ4M0MR1kUpVi0
|
||||
'';
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
############################################################
|
||||
# User configuration
|
||||
############################################################
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL4qWNZnYU5JaqR9c2qh6oFZktzVNBOx42PfDaGofCL6 cnclack@pm.me macbook"
|
||||
];
|
||||
|
||||
############################################################
|
||||
# Service configuration
|
||||
############################################################
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
systemd.services.NetworkManager-wait-online.enable = false;
|
||||
|
||||
systemd.services.zero-touch-install = {
|
||||
description = "Zero-Touch Kiosk Installation";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
# Make sure we own tty1 exclusively - getty@tty1 will otherwise
|
||||
# try to spawn a login prompt on the same console.
|
||||
conflicts = [ "getty@tty1.service" ];
|
||||
after = [ "systemd-udev-settle.service" "getty@tty1.service" ];
|
||||
|
||||
path = with pkgs; [
|
||||
nix
|
||||
git
|
||||
util-linux
|
||||
nixos-install-tools
|
||||
curl
|
||||
networkmanager
|
||||
mount
|
||||
umount
|
||||
disko
|
||||
];
|
||||
|
||||
environment = {
|
||||
NIX_PATH = "nixpkgs=${inputs.nixpkgs}";
|
||||
KIOSK_FLAKE = "${self}";
|
||||
DISKO_SCRIPT = "${diskoScript}";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
StandardInput = "tty";
|
||||
StandardOutput = "tty";
|
||||
StandardError = "tty";
|
||||
TTYPath = "/dev/tty1";
|
||||
TTYReset = true;
|
||||
TTYVHangup = true;
|
||||
TTYVTDisallocate = true;
|
||||
};
|
||||
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
|
||||
echo "Running disko script..."
|
||||
echo "Script: $DISKO_SCRIPT"
|
||||
|
||||
${diskoScript}
|
||||
|
||||
echo "Installing RadiantWave"
|
||||
echo "Closure Path: ${targetSystem}"
|
||||
|
||||
nixos-install \
|
||||
--system "${targetSystem}" \
|
||||
--no-root-passwd \
|
||||
--no-channel-copy
|
||||
|
||||
echo "============================================"
|
||||
echo " Installation complete!"
|
||||
echo " Please shut down and remove the flash drive before restarting"
|
||||
echo "============================================"
|
||||
sleep 10000000
|
||||
'';
|
||||
};
|
||||
}
|
||||
Generated
+14
-14
@@ -184,11 +184,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1776877367,
|
||||
"narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=",
|
||||
"lastModified": 1785967620,
|
||||
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0726a0ecb6d4e08f6adced58726b95db924cef57",
|
||||
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -200,11 +200,11 @@
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1776877367,
|
||||
"narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=",
|
||||
"lastModified": 1785967620,
|
||||
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0726a0ecb6d4e08f6adced58726b95db924cef57",
|
||||
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -220,11 +220,11 @@
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1786170011,
|
||||
"narHash": "sha256-Vx/3kwIQFRYDZQtVdcdGgJPnNa2Y44HRYZyJAeug6OI=",
|
||||
"lastModified": 1787522765,
|
||||
"narHash": "sha256-D3KOrGcAH07lvKYgyiwejOQpDW91js7zI6l87WdabLk=",
|
||||
"ref": "main",
|
||||
"rev": "312f5e2a90e03f32ce61d6db54f46b9adac60933",
|
||||
"revCount": 250,
|
||||
"rev": "63265cc22f3055a782a0114e92c57a36bef723b2",
|
||||
"revCount": 40,
|
||||
"type": "git",
|
||||
"url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git"
|
||||
},
|
||||
@@ -240,11 +240,11 @@
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1786170011,
|
||||
"narHash": "sha256-Vx/3kwIQFRYDZQtVdcdGgJPnNa2Y44HRYZyJAeug6OI=",
|
||||
"lastModified": 1787522765,
|
||||
"narHash": "sha256-D3KOrGcAH07lvKYgyiwejOQpDW91js7zI6l87WdabLk=",
|
||||
"ref": "dev",
|
||||
"rev": "312f5e2a90e03f32ce61d6db54f46b9adac60933",
|
||||
"revCount": 250,
|
||||
"rev": "63265cc22f3055a782a0114e92c57a36bef723b2",
|
||||
"revCount": 40,
|
||||
"type": "git",
|
||||
"url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git"
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
nixos-facter-modules.url = "github:numtide/nixos-facter-modules";
|
||||
radiantwave.url = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git?ref=main";
|
||||
radiantwave-dev.url = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git?ref=dev";
|
||||
# radiantwave-dev.url = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave-cpp.git?ref=dev";
|
||||
nixos-raspberrypi.url = "github:nvmd/nixos-raspberrypi/main";
|
||||
};
|
||||
|
||||
@@ -43,8 +42,8 @@
|
||||
rsvg-convert \
|
||||
--keep-aspect-ratio \
|
||||
--background-color=#111318 \
|
||||
--width=3840 \
|
||||
--height=2160 \
|
||||
--width=1280 \
|
||||
--height=720 \
|
||||
--output=$out/share/plymouth/themes/radiantwave/splash.png \
|
||||
$src
|
||||
sed 's,/usr/,'"$out"'/,g' ${./plymouth-theme/radiantwave.plymouth} \
|
||||
@@ -54,7 +53,16 @@
|
||||
'';
|
||||
};
|
||||
|
||||
mkKioskSystem = { system, radiantwave, upgradeFlakeRef, extraModules ? [], diskModule, extraSpecialArgs ? {}}:
|
||||
revision = self.rev or self.dirtyRev or null;
|
||||
|
||||
mkKioskSystem = {
|
||||
system,
|
||||
radiantwave,
|
||||
upgradeFlakeRef,
|
||||
hostName,
|
||||
diskModule,
|
||||
extraModules ? [],
|
||||
}:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
@@ -62,20 +70,35 @@
|
||||
inherit radiantwave;
|
||||
inherit upgradeFlakeRef;
|
||||
inherit radiantwavePlymouth;
|
||||
} // extraSpecialArgs;
|
||||
};
|
||||
|
||||
modules = [
|
||||
{ nixpkgs.config.allowUnfree = true; }
|
||||
{
|
||||
networking.hostName = hostName;
|
||||
system.configurationRevision = revision;
|
||||
}
|
||||
./configuration.nix
|
||||
disko.nixosModules.disko
|
||||
diskModule
|
||||
diskModule
|
||||
nixos-facter-modules.nixosModules.facter
|
||||
# Hardware facter report. This is a NUC 14 report currently
|
||||
# applied to every x86 variant (including commercial SATA
|
||||
# hardware). To use per-model reports: generate them on each
|
||||
# hardware target (procedure in AGENTS.md), commit them as
|
||||
# facter-<model>.json, and select per variant here, e.g.:
|
||||
# { facter.reportPath = ./facter-commercial.json; }
|
||||
{ facter.reportPath = ./facter.json; }
|
||||
radiantwave.nixosModules.default
|
||||
] ++ extraModules;
|
||||
};
|
||||
|
||||
mkRpiKioskSystem = { radiantwave, upgradeFlakeRef, extraModules ? [] }:
|
||||
mkRpiKioskSystem = {
|
||||
radiantwave,
|
||||
upgradeFlakeRef,
|
||||
hostName,
|
||||
extraModules ? [],
|
||||
}:
|
||||
nixos-raspberrypi.lib.nixosSystem {
|
||||
specialArgs = {
|
||||
inherit radiantwave upgradeFlakeRef;
|
||||
@@ -95,6 +118,9 @@
|
||||
./configuration.nix
|
||||
radiantwave.nixosModules.default
|
||||
{
|
||||
networking.hostName = hostName;
|
||||
system.configurationRevision = revision;
|
||||
|
||||
boot.loader.systemd-boot.enable = nixpkgs.lib.mkForce false;
|
||||
boot.loader.efi.canTouchEfiVariables = nixpkgs.lib.mkForce false;
|
||||
boot.loader.raspberry-pi.bootloader = "kernel";
|
||||
@@ -108,155 +134,137 @@
|
||||
}
|
||||
] ++ extraModules;
|
||||
};
|
||||
|
||||
# Zero-touch USB installer image. `targetConfig` names the kiosk system
|
||||
# to install: the closure comes from the packages output below and the
|
||||
# partitioning script from the paired disk module, so the ISO always
|
||||
# installs the matching system for its hardware.
|
||||
mkIso = { targetConfig, diskModule }:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit self;
|
||||
};
|
||||
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||
disko.nixosModules.disko
|
||||
(import ./zero-touch-installer.nix { inherit targetConfig; })
|
||||
diskModule
|
||||
({ pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
disko.packages.${system}.default
|
||||
];
|
||||
isoImage.storeContents = [
|
||||
self.packages.x86_64-linux.${targetConfig}
|
||||
];
|
||||
environment.etc."disko-config.nix".source = diskModule;
|
||||
})
|
||||
];
|
||||
};
|
||||
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;
|
||||
# Kiosk
|
||||
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.
|
||||
#
|
||||
# Production variants consume the `radiantwave` input (?ref=main);
|
||||
# `-dev` variants consume `radiantwave-dev` (?ref=dev) and track the
|
||||
# dev branch of this repo via their autoUpgrade flake refs.
|
||||
nixosConfigurations = {
|
||||
radiantwavekiosk = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
hostName = "radiantwavekiosk";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk";
|
||||
extraModules = [];
|
||||
};
|
||||
# Kiosk-dev
|
||||
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 = [];
|
||||
};
|
||||
# Commercial
|
||||
radiantwavekiosk-commercial = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
hostName = "radiantwavekiosk-commercial";
|
||||
diskModule = ./commercial-disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-commercial";
|
||||
extraModules = [];
|
||||
};
|
||||
# Commercial-dev
|
||||
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";
|
||||
extraModules = [];
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git?ref=dev#radiantwavekiosk-commercial-dev";
|
||||
};
|
||||
# Kiosk - rotated screen for android displays
|
||||
# Rotated screen for android-style displays.
|
||||
radiantwavekiosk-android = mkKioskSystem {
|
||||
system = "x86_64-linux";
|
||||
radiantwave = radiantwave;
|
||||
hostName = "radiantwavekiosk-android";
|
||||
diskModule = ./disk-config.nix;
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-android";
|
||||
extraModules = [./rotated_display.nix ];
|
||||
extraModules = [./rotated_display.nix];
|
||||
};
|
||||
# Raspberry pi 5
|
||||
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];
|
||||
};
|
||||
# Raspberry Pi 5.
|
||||
radiantwavekiosk-rpi = mkRpiKioskSystem {
|
||||
radiantwave = radiantwave;
|
||||
hostName = "radiantwavekiosk-rpi";
|
||||
upgradeFlakeRef = "git+https://gitea.radiantwavetech.com/RadiantWaveTech/KioskConfig.git#radiantwavekiosk-rpi";
|
||||
};
|
||||
# Raspberry pi 5 dev
|
||||
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";
|
||||
};
|
||||
|
||||
# === USB Images ===
|
||||
# Kiosk ISO
|
||||
kiosk-iso = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit self;
|
||||
};
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||
disko.nixosModules.disko
|
||||
./iso-config.nix
|
||||
./disk-config.nix
|
||||
({ pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
disko.packages.${system}.default
|
||||
];
|
||||
isoImage.storeContents = [
|
||||
self.packages.x86_64-linux.radiantwavekiosk
|
||||
];
|
||||
environment.etc."disko-config.nix".source = ./disk-config.nix;
|
||||
})
|
||||
];
|
||||
# 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.
|
||||
kiosk-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk";
|
||||
diskModule = ./disk-config.nix;
|
||||
};
|
||||
# Commercial iso
|
||||
commercial-iso = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit self;
|
||||
};
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||
disko.nixosModules.disko
|
||||
./commercial-iso-config.nix
|
||||
./commercial-disk-config.nix
|
||||
({ pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
disko.packages.${system}.default
|
||||
];
|
||||
isoImage.storeContents = [
|
||||
self.packages.x86_64-linux.radiantwavekiosk-commercial
|
||||
];
|
||||
environment.etc."disko-config.nix".source = ./commercial-disk-config.nix;
|
||||
})
|
||||
];
|
||||
commercial-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk-commercial";
|
||||
diskModule = ./commercial-disk-config.nix;
|
||||
};
|
||||
# kiosk rotated screen ISO
|
||||
android-iso = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit self;
|
||||
};
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||
disko.nixosModules.disko
|
||||
./iso-config.nix
|
||||
./disk-config.nix
|
||||
({ pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
disko.packages.${system}.default
|
||||
];
|
||||
isoImage.storeContents = [
|
||||
self.packages.x86_64-linux.radiantwavekiosk-android
|
||||
];
|
||||
environment.etc."disko-config.nix".source = ./disk-config.nix;
|
||||
})
|
||||
];
|
||||
android-iso = mkIso {
|
||||
targetConfig = "radiantwavekiosk-android";
|
||||
diskModule = ./disk-config.nix;
|
||||
};
|
||||
# Kiosk iso development branch
|
||||
dev-iso = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit self;
|
||||
};
|
||||
modules = [
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||
disko.nixosModules.disko
|
||||
./dev-iso.nix
|
||||
./disk-config.nix
|
||||
({ pkgs, ... }: {
|
||||
environment.systemPackages = [
|
||||
disko.packages.${system}.default
|
||||
];
|
||||
isoImage.storeContents = [
|
||||
self.packages.x86_64-linux.radiantwavekiosk-dev
|
||||
];
|
||||
environment.etc."disko-config.nix".source = ./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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
KioskConfig Commit,Date (CDT),URL Change,Pinned App Revision,App Revision Date,App Version on Home Screen
|
||||
c06a3f7,2026-07-27 14:13,"codeberg.org/RhemaWave-Technologies/RhemaWave.git",9f8212cf550b,2026-06-27,2.3.5.8
|
||||
5a6031a,2026-07-27 14:23,Codeberg → gitea.radiantwavetech.com/.../RhemaWave.git,9f8212cf550b,2026-06-27,2.3.5.8
|
||||
7f2f19f,2026-07-27 14:24,RhemaWave.git → radiantwave.git,9f8212cf550b,2026-06-27,2.3.5.8
|
||||
4af16d9,2026-07-28 10:43,Add ?ref=main,6ad6516a7461,2026-07-02,Coming Soon
|
||||
cbb3e05,2026-08-07 17:13,Dev → radiantwave-cpp.git?ref=dev,b54dbca2d5e7,2026-08-03,07292026_1618
|
||||
37d18d3,2026-08-07 17:18,Fix: dropped git+ prefix on dev URL,b54dbca2d5e7,2026-08-03,07292026_1618
|
||||
50a1f3e,2026-08-07 17:19,Fix: restored git+ prefix on dev URL,b54dbca2d5e7,2026-08-03,07292026_1618
|
||||
e3120f2,2026-08-08 00:02,Dev back to radiantwave.git?ref=dev,b54dbca2d5e7,2026-08-03,07292026_1618
|
||||
50176d8,2026-08-17 10:51,New radiantwave-legacy input added,312f5e2a90e0,2026-08-08,08082026_0120
|
||||
0cb1337,2026-08-17 10:57,Auth token added to legacy URL,312f5e2a90e0,2026-08-08,08082026_0120
|
||||
fb2f861,2026-08-17 12:48,Prod pointed to radiantwave-legacy.git,312f5e2a90e0,2026-08-08,08082026_0120
|
||||
027d1a6,2026-08-17 12:50,Token rotated (fb62d6c → 794ef1d),312f5e2a90e0,2026-08-08,08082026_0120
|
||||
14463ad,2026-08-17 12:52,Token removed (repo made public),312f5e2a90e0,2026-08-08,08082026_0120
|
||||
e09758a,2026-08-17 12:54,HTTPS → SSH (:2222),312f5e2a90e0,2026-08-08,08082026_0120
|
||||
|
+10
-1
@@ -2,8 +2,17 @@
|
||||
let
|
||||
radiantApp = radiantwave.packages.${pkgs.system}.default;
|
||||
kioskscript = pkgs.writeShellScript "kiosk-start" ''
|
||||
# Wait for the Wayland display to be ready
|
||||
for i in {1..10}; do
|
||||
if ${pkgs.wlr-randr}/bin/wlr-randr &>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
OUTPUT=$(${pkgs.wlr-randr}/bin/wlr-randr | grep -m1 '^\S' | awk '{print $1}')
|
||||
${pkgs.wlr-randr}/bin/wlr-randr --output "$OUTPUT" --transform 90
|
||||
echo "Rotating output: $OUTPUT" >> /tmp/kiosk.log
|
||||
${pkgs.wlr-randr}/bin/wlr-randr --output "$OUTPUT" --transform 90 >> /tmp/kiosk.log 2>&1 || echo "wlr-randr failed" >> /tmp/kiosk.log
|
||||
exec ${radiantApp}/bin/radiantwave -d -s
|
||||
'';
|
||||
in
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
Date (CDT),KioskConfig Hash,RadiantWave Hash,App Version,Summary
|
||||
2026-03-12 08:05:10 -0500,,403ec4db89b5,dev,Initial release: RadiantWave v1.0
|
||||
2026-03-13 19:57:06 -0500,,ee2b3383a8da,dev,Fix WiFi password entry
|
||||
2026-03-13 20:14:01 -0500,,c68757a63439,dev,Update version
|
||||
2026-03-13 20:28:41 -0500,,91e5c04a3800,dev,Update version
|
||||
2026-03-13 20:58:28 -0500,,5fef01107b03,dev,Attempt to fix wifi connectivity
|
||||
2026-03-13 20:59:02 -0500,,a116e01146e9,dev,update version
|
||||
2026-03-13 21:13:21 -0500,,5f254e94cd55,dev,Fix WiFi page update
|
||||
2026-03-13 21:16:54 -0500,,f8fbfb721d3d,dev,Update version
|
||||
2026-03-23 15:02:07 -0500,,17c088cc2fc2,dev,Update Database
|
||||
2026-03-23 17:35:52 -0500,,8d2384139116,dev,Pull Proclamations & Categories from API and store them in the database
|
||||
2026-03-24 11:19:50 -0500,,9b6bae9511ab,dev,List proclamations inside of categories
|
||||
2026-03-25 11:27:16 -0500,,678d679b536d,dev,Fix bug loading 0 proclamations
|
||||
2026-03-25 18:09:02 -0500,,465928915c2c,dev,Update version
|
||||
2026-03-25 19:56:41 -0500,,c1c077dc698d,dev,Update asset locations and permissions
|
||||
2026-03-25 20:33:58 -0500,,4aeaaf10b7d2,dev,Simplify asset handling
|
||||
2026-03-29 23:41:16 -0500,,6e28b90ee860,dev,"Add wifi, license and email checks"
|
||||
2026-03-30 00:08:52 -0500,,aea646f78868,dev,Set default volume to MAX
|
||||
2026-03-30 00:10:21 -0500,,331a8255fd5d,v1.0.0,Set version to 1.0.0 statically
|
||||
2026-03-30 00:43:01 -0500,,120772175d42,v1.0.0,Update Proclamation selection
|
||||
2026-04-13 14:00:02 -0500,,105d8900d58d,v1.0.0,Replace audio devices with audio toggle
|
||||
2026-04-13 14:09:26 -0500,,76fd6057778b,v1.0.0,Update changelog
|
||||
2026-04-15 11:01:28 -0500,,b6bf0f1873b7,v1.0.0,Sync proclamations when entering proclamation list
|
||||
2026-04-15 11:58:44 -0500,,10ba5df13261,v1.0.0,Force re-initialization of audio device when Play() is called
|
||||
2026-04-15 13:56:53 -0500,,b94279be691a,v1.0.0,Update changelog
|
||||
2026-04-17 11:43:59 -0500,,504095caa826,v1.0.0,Sync instead of download.
|
||||
2026-04-23 16:44:09 -0500,,dd069e934508,1.0,WIP: Stagger proclamations
|
||||
2026-04-24 11:06:50 -0500,,7f344ae5c806,1.0,Optimize proclamation loading
|
||||
2026-05-06 10:16:19 -0500,,3cf3e4cf23f3,1.0,Fix database syncronization
|
||||
2026-05-10 21:19:07 -0500,,87d484353fb0,1.0,Fixed WiFi password bug. Ready for testing and merge
|
||||
2026-05-11 12:55:16 -0500,,1f9da7ee780a,1.0,Attempt to fix proclamation sync
|
||||
2026-05-14 09:57:13 -0500,,3ea32e0eaa36,1.0,Add volume changing logic
|
||||
2026-05-14 10:21:11 -0500,,5188c90350d8,1.0,Add working volume bar in audioDevices page
|
||||
2026-05-26 14:12:27 -0500,,f7ef42c84ab5,1.0,Rename application to Radiant Wave
|
||||
2026-05-31 12:08:19 -0500,,0ebc3adf4ae5,1.0,Proclamations change colors!
|
||||
2026-05-31 12:15:10 -0500,,8268022d5128,1.0,Organize proclamations alphabetically
|
||||
2026-06-03 11:21:28 -0500,,ddab8e446c6b,1.0.0-beta,Update version for visual preference during beta phase
|
||||
2026-06-11 19:44:20 -0500,,4b7d2c13d5ce,1.0.0-beta,Rename audio devices to audio options
|
||||
2026-06-18 08:02:21 -0500,,6b4867953756,1.0.0-beta,Add database logic
|
||||
2026-06-18 11:29:45 -0500,,fe5543d50dea,1.0.0-beta,Audio downloads when necessary
|
||||
2026-06-18 15:39:30 -0500,,a5f9780f410b,1.0.0-beta,Add download package
|
||||
2026-06-18 15:49:05 -0500,,1a67b9780400,1.0.0-beta,un-mask wifi password
|
||||
2026-06-18 15:49:29 -0500,,b11afe22f09e,1.0.0-beta,remove file downloads
|
||||
2026-06-18 21:28:16 -0500,,7ecb90b63b61,1.0,Downloads are working and the goroutine is reporting updates appropriately.
|
||||
2026-06-18 21:52:29 -0500,,2af1aae88580,1.0,Audio files download on application start. Home screen shows status message
|
||||
2026-06-18 22:43:47 -0500,,ac86864c7286,1.0,Add downloading message to home screen.
|
||||
2026-06-18 22:51:17 -0500,,1c814f4abb6b,1.0,Reset default volume to MAX
|
||||
2026-06-19 00:13:25 -0500,,4cd24375cdac,1.0,Add audio features
|
||||
2026-06-23 11:22:21 -0500,,30dd5ffdcb94,1.0,Create objects for tracking audio devices
|
||||
2026-06-24 14:17:06 -0500,,0a9a33b87b90,1.0,Fix download URL mismatch
|
||||
2026-06-24 14:50:13 -0500,,970b8ebf09af,1.0,Add verbose logging to download.DownloadAudioFiles
|
||||
2026-06-24 14:57:42 -0500,,cc2887d2a06d,b018a79,Update version text and add more download logs
|
||||
2026-06-24 18:29:59 -0500,,953d0d8bc93d,b018a79,Rewrite entire network package and update wifi page
|
||||
2026-06-24 22:41:48 -0500,,a4eff17b77a1,b018a79,"fix(network): fix wifi page never scanning, never exiting, and UI freezes on connect"
|
||||
2026-06-24 23:18:32 -0500,,57500308b00d,b018a79,Handle locked database cases
|
||||
2026-06-24 23:20:57 -0500,,f8e75194e845,cd79a6f,Update version hash for visual verification
|
||||
2026-06-26 18:07:12 -0500,,4dd78b5ade8a,9beeeb1,Update version number for visual validation
|
||||
2026-06-27 00:37:07 -0500,,2fac3ab6a8aa,9beeeb1,Replace textInputSupported flag
|
||||
2026-06-27 01:47:06 -0500,,ca18000c8ef4,2.3.5.8,Update version string for validation
|
||||
2026-06-27 12:57:29 -0500,,18c57c9101bf,2.3.5.8,Remove calls to RefreshConfig
|
||||
2026-06-27 13:59:22 -0500,,f00cb9efb6a0,2.3.5.8,Fix download progress and prevent re-downloading existing audio.
|
||||
2026-06-27 14:25:25 -0500,,2c88b7ffc515,2.3.5.8,Add creation of audio directory and remove unused function in download package
|
||||
2026-06-27 14:25:51 -0500,,0b43a982985b,2.3.5.8,Remove unused function in download package
|
||||
2026-06-27 14:50:50 -0500,,8ec1cbbc480b,2.3.5.8,Log the app config in Debug
|
||||
2026-06-27 15:09:51 -0500,,ba39ed85a943,2.3.5.8,Remove wal and shm deletion
|
||||
2026-06-27 16:01:33 -0500,,7e598f191f72,2.3.5.8,Update Network package
|
||||
2026-06-27 16:51:18 -0500,,b0947bd59447,2.3.5.8,Fix bugs in WiFi page
|
||||
2026-06-28 01:56:35 -0500,,193ebbcb2714,2.3.5.8,Fix network connection timeouts and security detection
|
||||
2026-06-28 15:11:35 -0500,,6ad8a19f2ad9,2.3.5.8,Increase startup volume to 1.0
|
||||
2026-06-28 15:18:27 -0500,,c232d417ba31,Coming Soon,Update version string
|
||||
2026-07-10 13:56:06 -0500,,2bcb36669fd2,Coming Soon,fix: restore SDL volume to MAX after device switch
|
||||
2026-07-10 13:56:12 -0500,,9bc0fd6820bb,Coming Soon,fix: restore SDL volume to MAX after device switch
|
||||
2026-07-10 14:00:48 -0500,,68b3680e32bc,Coming Soon,fix: make wayland/X11 buildInputs Linux-only for macOS dev shell
|
||||
2026-07-10 14:18:47 -0500,,779bc77c5b45,Coming Soon,fix: use recursiveUpdate instead of // to preserve packages.default
|
||||
2026-07-10 16:02:02 -0500,,313db8ccd18a,Coming Soon,fix: rewrite cmd_diagnose to use script upload instead of nested SSH quoting
|
||||
2026-07-10 17:12:48 -0500,,fca635482901,Coming Soon,Create Docker build pipeline for MacOS
|
||||
2026-07-11 09:01:05 -0500,,141613f571ed,Audio-Bug-Fix 0.1,Update version string to indicate audio-bug-fixes
|
||||
2026-07-11 09:45:12 -0500,,9dc1ce77aefc,Audio-Bug-Fix 0.1,WIP on dev: 141613f Update version string to indicate audio-bug-fixes
|
||||
2026-07-11 09:45:12 -0500,,bdbc525b6fb7,Audio-Bug-Fix 0.1,index on dev: 141613f Update version string to indicate audio-bug-fixes
|
||||
2026-07-11 10:16:15 -0500,,72910e700605,Audio-Bug-Fix 0.1,fix: prevent Play() deadlock when device is not open
|
||||
2026-07-11 11:39:58 -0500,,bb132ceeaf86,Audio-Bug-Fix 0.5,fix: resolve 4 critical audio mixer bugs (v0.5)
|
||||
2026-07-11 13:43:05 -0500,,3f8144a708bb,Audio-Bug-Fix 0.6,Gate READY on download completion; move audio to ~/.radiantwave/audio
|
||||
2026-07-11 15:27:01 -0500,,336f407499f4,Audio-Bug-Fix 0.6,Allow F2/F3 during DOWNLOADING_ASSETS state
|
||||
2026-07-11 16:36:15 -0500,,a93e47589984,Audio-Bug-Fix 0.6,Fix double-close panic on DownloadDone channel
|
||||
2026-07-11 16:43:16 -0500,,2ef826fe635b,Audio-Bug-Fix 0.6,Fix double-close panic on DownloadDone: skip re-navigation between HOME-mapped states
|
||||
2026-07-11 17:10:59 -0500,,f29d1d1af51e,07112026-1710,Bump version to 07112026-1710; move completed items to release section
|
||||
2026-07-12 18:15:41 -0500,,c98b84a3a8f3,07112026-1710,fix: active device highlight incorrect when using default device
|
||||
2026-07-12 18:16:18 -0500,,e090870b4dfd,07112026-1710,fix: SwitchDevice no longer passes 'system default' to SDL
|
||||
2026-07-12 18:17:22 -0500,,5854c57f6f01,07112026-1710,"changelog: update fixed issues list, remove known issues"
|
||||
2026-07-27 13:14:37 -0500,,b1a5a670ab0b,07112026-1710,Add audio list
|
||||
2026-07-27 14:13:58 -0500,c06a3f7f92de,,07112026-1710,init new repo
|
||||
2026-07-27 14:23:31 -0500,5a6031a3fe5a,,07112026-1710,refactor: migrate from Codeberg to Gitea and rename rhemawave to radiantwave
|
||||
2026-07-27 14:24:25 -0500,7f2f19fe41d9,,07112026-1710,fix: use correct lowercase repo name radiantwave.git
|
||||
2026-07-27 14:29:03 -0500,26aca21e963d,,07112026-1710,Update flake.lock
|
||||
2026-07-28 14:10:44 +0000,16545a77fd7e,,07112026-1710,chore: update radiantwave-dev to latest dev
|
||||
2026-07-28 10:43:06 -0500,4af16d9df7c4,,07112026-1710,Specify main branch
|
||||
2026-07-29 14:46:11 -0500,,6dda46288473,07292026_1445,Add audio selection
|
||||
2026-07-29 14:57:32 -0500,,7a3b6a66b72f,07292026_1445,"Remove wpctl parsing tests (TestParseSinkLine, TestParseSinks)"
|
||||
2026-07-29 14:58:15 -0500,,3480e7594a3b,07292026_1445,Replace wpctl volume control with SDL_mixer VolumeMusic
|
||||
2026-07-29 16:19:15 -0500,,91711eef9328,07292026_1618,"Replace AudioFile with AudioTrack, fix download+orphan+MD5 sync, always play original audio fallback"
|
||||
2026-07-29 19:40:04 -0500,09bc293af31e,,07292026_1618,Chore: Update RadiantWave
|
||||
2026-08-02 00:56:34 -0500,ab6488028120,,07292026_1618,Organize flakes and cleanup things.
|
||||
2026-08-03 01:54:27 -0500,,11b25227d789,07292026_1618,"Rename app to radiantwave: embed and provision assets, drop proclamations"
|
||||
2026-08-03 01:54:52 -0500,ce6856b37a09,,07292026_1618,"Fix kiosk startup: radiantwave binary, drop stale rsync, fix GODEBUG typo"
|
||||
2026-08-03 07:26:16 +0000,8ef25f756076,,07292026_1618,chore: update radiantwave-dev to latest
|
||||
2026-08-03 02:40:51 -0500,,b54dbca2d5e7,07292026_1618,Fix asset provisioning to strip embedded share/radiantwave root
|
||||
2026-08-06 10:13:40 -0500,0f5aa7670cf9,,07292026_1618,Chore: Update Radiantwave
|
||||
2026-08-06 21:55:40 -0500,c3f65f78976f,,07292026_1618,Fix audio: pin system volume to 100% before RadiantWave launches
|
||||
2026-08-07 00:38:25 -0500,2d4aca230d04,,07292026_1618,Update configuration and dev-iso
|
||||
2026-08-07 17:13:59 -0500,cbb3e0585970,,07292026_1618,"Update to radiantave-cpp, enable plymouth boot image"
|
||||
2026-08-07 17:18:32 -0500,37d18d3f474b,,07292026_1618,Update repository location
|
||||
2026-08-07 17:19:04 -0500,50a1f3e99dfc,,07292026_1618,Update repository location
|
||||
2026-08-07 17:39:26 -0500,06f02d49b910,,07292026_1618,update radiantwave to radiatnwave-dev
|
||||
2026-08-07 17:47:04 -0500,2e3d88b57dce,,07292026_1618,Update Plymount dontUnpack = true;
|
||||
2026-08-07 22:17:52 -0500,4580319f19f5,,07292026_1618,Update radiantwave-dev
|
||||
2026-08-07 23:58:25 -0500,8abb028c8260,,07292026_1618,fix wpctl volume pinning
|
||||
2026-08-08 00:02:09 -0500,e3120f27c20b,,07292026_1618,Pull back from radiantwave-cpp-dev to radiantwave-dev
|
||||
2026-08-08 00:12:57 -0500,,2212cc9b7805,07292026_1618,Add audio device switching UI
|
||||
2026-08-08 01:20:11 -0500,,312f5e2a90e0,08082026_0120,Rename rhemawave to radiantwave throughout
|
||||
2026-08-08 06:25:05 +0000,1f3e194aa558,,08082026_0120,Chore: Update Radiantwave-dev
|
||||
2026-08-08 01:44:03 -0500,240be2540f3f,,08082026_0120,Update Radiantwave
|
||||
2026-08-17 10:44:36 -0500,06c2a7cd0a1e,,08082026_0120,Add plan to migrate to DRM
|
||||
2026-08-17 10:51:05 -0500,50176d8fd5e4,,08082026_0120,"repoint production to radiantwave-legacy, dev to radiantwave (ref=main)"
|
||||
2026-08-17 10:57:16 -0500,0cb1337f18fd,,08082026_0120,"add radiantwave-legacy input with auth token, update flake.lock"
|
||||
2026-08-17 11:02:19 -0500,2abdfa2b9b28,,08082026_0120,revert upgradeFlakeRef URLs to KioskConfig to match renamed repo
|
||||
2026-08-17 12:43:57 -0500,974a61051883,,08082026_0120,Update dev images to new radiantwave
|
||||
2026-08-17 12:48:22 -0500,fb2f86125804,,08082026_0120,Revert back to Legacy Radiant Wave
|
||||
2026-08-17 12:50:20 -0500,027d1a628feb,,08082026_0120,Update token
|
||||
2026-08-17 12:52:11 -0500,14463ad99b08,,08082026_0120,Just make RadiantWave-Legacy public
|
||||
2026-08-17 12:54:06 -0500,e09758a70ece,,08082026_0120,fix: switch radiantwave inputs to SSH for legacy Go repo
|
||||
|
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Archive old build images on the fileserver before publishing new ones.
|
||||
#
|
||||
# Usage: tools/archive-images.sh <ssh-target> <images-dir> <archive-dir> <pattern>...
|
||||
#
|
||||
# Zero matching files is fine (nothing to archive yet); a missing directory
|
||||
# or a failed move aborts non-zero so CI stops before publishing.
|
||||
# The remote half is piped to `bash -s` over stdin so there is no nested
|
||||
# shell quoting to get wrong.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
|
||||
(( $# >= 4 )) || die "usage: $0 <ssh-target> <images-dir> <archive-dir> <pattern>..."
|
||||
|
||||
target=$1 images_dir=$2 archive_dir=$3
|
||||
shift 3
|
||||
patterns=("$@")
|
||||
|
||||
for v in "$images_dir" "$archive_dir" "${patterns[@]}"; do
|
||||
case $v in
|
||||
*[[:space:]\'\"]*) die "unsafe argument (whitespace/quotes): $v" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Archiving previous images on $target:"
|
||||
printf ' pattern: %s\n' "${patterns[@]}"
|
||||
|
||||
# Assignments prefixed to `bash -s` are parsed by the remote shell as
|
||||
# environment variables for the script below; the quoted heredoc marker
|
||||
# keeps every byte of the payload literal until bash executes it.
|
||||
ssh "$target" "IMAGES_DIR=$images_dir ARCHIVE_DIR=$archive_dir bash -s" <<'REMOTE'
|
||||
set -euo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
if [ ! -d "$IMAGES_DIR" ]; then
|
||||
echo "error: images dir not found: $IMAGES_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$ARCHIVE_DIR" ]; then
|
||||
echo "error: archive dir not found: $ARCHIVE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
moved=0
|
||||
for pat in "${PATTERNS[@]}"; do
|
||||
for f in "$IMAGES_DIR"/$pat; do
|
||||
echo " archiving $(basename "$f")"
|
||||
mv "$f" "$ARCHIVE_DIR/"
|
||||
moved=$((moved + 1))
|
||||
done
|
||||
done
|
||||
|
||||
echo "Archived $moved file(s)."
|
||||
REMOTE
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env zsh
|
||||
#
|
||||
# find_systems.zsh
|
||||
# Sweeps a subnet for hosts with SSH open, then queries each as `kiosk`
|
||||
# for hostname + NixOS configuration revision.
|
||||
#
|
||||
# Usage: ./find_systems.zsh [subnet]
|
||||
# subnet defaults to 192.168.4.0/24
|
||||
|
||||
set -uo pipefail # no -e: we want to keep going past unreachable hosts
|
||||
|
||||
SUBNET="${1:-192.168.4.0/24}"
|
||||
SSH_USER="kiosk"
|
||||
SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new)
|
||||
|
||||
echo "Scanning $SUBNET for open SSH (22)..."
|
||||
ips=("${(@f)$(nmap -p 22 --open -Pn "$SUBNET" -oG - | awk '/22\/open/ {print $2}')}")
|
||||
|
||||
if [[ ${#ips[@]} -eq 0 ]]; then
|
||||
echo "No hosts with open SSH found on $SUBNET."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Found ${#ips[@]} host(s). Querying..."
|
||||
echo
|
||||
|
||||
fail_count=0
|
||||
|
||||
for ip in "${ips[@]}"; do
|
||||
echo "== $ip =="
|
||||
if ssh "${SSH_OPTS[@]}" "${SSH_USER}@${ip}" \
|
||||
'echo "host: $(hostname)"; echo "rev: $(nixos-version --configuration-revision)"'; then
|
||||
:
|
||||
else
|
||||
echo " (unreachable or auth failed)"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo
|
||||
done
|
||||
|
||||
echo "Done. ${fail_count} of ${#ips[@]} host(s) failed to respond."
|
||||
@@ -1,3 +1,13 @@
|
||||
# Parameterized zero-touch installer for kiosk USB images.
|
||||
#
|
||||
# Usage in flake.nix:
|
||||
# (import ./zero-touch-installer.nix { targetConfig = "radiantwavekiosk"; })
|
||||
#
|
||||
# `targetConfig` must name an entry in self.nixosConfigurations. The target
|
||||
# closure and its disko partitioning script are derived from that config, so
|
||||
# an image can never install a mismatched system or format the wrong disk
|
||||
# layout as long as flake.nix pairs each ISO with its disk-config.nix.
|
||||
{ targetConfig }:
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
@@ -5,17 +15,15 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
targetSystem =
|
||||
self.nixosConfigurations.radiantwavekiosk.config.system.build.toplevel;
|
||||
cfg = self.nixosConfigurations.${targetConfig};
|
||||
targetSystem = cfg.config.system.build.toplevel;
|
||||
diskoScript = cfg.config.system.build.diskoScript;
|
||||
|
||||
diskoScript =
|
||||
self.nixosConfigurations.radiantwavekiosk.config.system.build.diskoScript;
|
||||
# Keep in sync with myKey in configuration.nix.
|
||||
adminKey =
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL4qWNZnYU5JaqR9c2qh6oFZktzVNBOx42PfDaGofCL6 cnclack@pm.me macbook";
|
||||
in
|
||||
{
|
||||
############################################################
|
||||
# System configuration
|
||||
############################################################
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
@@ -38,32 +46,11 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
nix.extraOptions = ''
|
||||
netrc-file = /etc/nix/netrc
|
||||
'';
|
||||
|
||||
environment.variables.KIOSK_FLAKE = "${self}";
|
||||
|
||||
environment.etc."nix/netrc" = {
|
||||
text = ''
|
||||
password eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIwODgzODk2ODEsIm5iZiI6MTc3MjgxMzY4MSwic3ViIjoia2lvc2siLCJodHRwczovL2p3dC5hdHRpYy5ycy92MSI6eyJjYWNoZXMiOnsia2lvc2siOnsiciI6MX19fX0.N6Ktrmmu1LSy2PP8uNF25VHRP1dxPZJ4M0MR1kUpVi0
|
||||
'';
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
############################################################
|
||||
# User configuration
|
||||
############################################################
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL4qWNZnYU5JaqR9c2qh6oFZktzVNBOx42PfDaGofCL6 cnclack@pm.me macbook"
|
||||
];
|
||||
|
||||
############################################################
|
||||
# Service configuration
|
||||
############################################################
|
||||
users.users.root.openssh.authorizedKeys.keys = [ adminKey ];
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
@@ -115,7 +102,7 @@ in
|
||||
|
||||
${diskoScript}
|
||||
|
||||
echo "Installing RadiantWave"
|
||||
echo "Installing RadiantWave (${targetConfig})"
|
||||
echo "Closure Path: ${targetSystem}"
|
||||
|
||||
nixos-install \
|
||||
@@ -127,7 +114,7 @@ in
|
||||
echo " Installation complete!"
|
||||
echo " Please shut down and remove the flash drive before restarting"
|
||||
echo "============================================"
|
||||
sleep 10000000
|
||||
sleep infinity
|
||||
'';
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user