From d583fac582888b1014869af8a5aa4df9f0a98897 Mon Sep 17 00:00:00 2001 From: UGA Innovation Factory Date: Fri, 12 Dec 2025 16:12:24 -0500 Subject: [PATCH] working on the stateless kiosk, dynamic hostnames not yet working --- .gitignore | 1 + sw/stateless-kiosk/default.nix | 27 +++------ sw/stateless-kiosk/kiosk-browser.nix | 91 ++++++++-------------------- sw/stateless-kiosk/mac-hostmap.nix | 27 +++++++++ sw/stateless-kiosk/net.nix | 2 +- sw/stateless-kiosk/programs.nix | 7 +++ sw/stateless-kiosk/services.nix | 54 +++++++++++++++++ 7 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 sw/stateless-kiosk/mac-hostmap.nix create mode 100644 sw/stateless-kiosk/programs.nix create mode 100644 sw/stateless-kiosk/services.nix diff --git a/.gitignore b/.gitignore index e370078..ca8e321 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ result/ result +deploy \ No newline at end of file diff --git a/sw/stateless-kiosk/default.nix b/sw/stateless-kiosk/default.nix index 99b4a6a..4b051c2 100644 --- a/sw/stateless-kiosk/default.nix +++ b/sw/stateless-kiosk/default.nix @@ -1,5 +1,5 @@ -# This module defines the software stack for a stateless kiosk. -# It includes a custom Firefox wrapper, Cage (Wayland kiosk compositor), and specific networking configuration. +## This module defines the software stack for a stateless kiosk. +# It now uses Sway (Wayland compositor) and Chromium in kiosk mode. { config, lib, @@ -9,22 +9,15 @@ }: lib.mkMerge [ (import ./kiosk-browser.nix { - inherit - config - lib - pkgs - inputs - ; + inherit config lib pkgs inputs; + }) + (import ./services.nix { + inherit config lib pkgs inputs; }) (import ./net.nix { - inherit - config - lib - pkgs - inputs - ; + inherit config lib pkgs inputs; + }) + (import ./programs.nix { + inherit config lib pkgs inputs; }) - { - services.openssh.enable = false; - } ] diff --git a/sw/stateless-kiosk/kiosk-browser.nix b/sw/stateless-kiosk/kiosk-browser.nix index e34d039..4cc2c74 100644 --- a/sw/stateless-kiosk/kiosk-browser.nix +++ b/sw/stateless-kiosk/kiosk-browser.nix @@ -1,52 +1,14 @@ -# This module configures Firefox for kiosk mode. -# It wraps Firefox with specific policies to disable UI elements and lock down the browser. -# It also includes a startup script that determines the kiosk URL based on the machine's MAC address. + +# This module configures Chromium for kiosk mode under Sway. +# It includes a startup script that determines the kiosk URL based on the machine's MAC address. { config, lib, pkgs, ... }: let - kioskPolicies = { - DisableAppUpdate = true; - DisableFirefoxStudies = true; - DisableTelemetry = true; - DisablePocket = true; - DisableSetDesktopBackground = true; - DisableFeedbackCommands = true; - DontCheckDefaultBrowser = true; - OverrideFirstRunPage = ""; - OverridePostUpdatePage = ""; - NoDefaultBookmarks = true; - DisableProfileImport = true; - - Permissions = { - Camera = { Allow = ["homeassistant.lan"]; }; - Microphone = { Allow = ["homeassistant.lan"]; }; - Location = { Allow = ["homeassistant.lan"]; }; - Notifications = { Allow = ["homeassistant.lan"]; }; - Clipboard = { Allow = ["homeassistant.lan"]; }; - Fullscreen = { Allow = ["homeassistant.lan"]; }; - }; + macCaseBuilder = (import ./mac-hostmap.nix { inherit lib; }).macCaseBuilder; + macCases = macCaseBuilder { + varName = "STATION"; }; - - extraPrefs = pkgs.writeText "kiosk-prefs.js" '' - pref("browser.shell.checkDefaultBrowser", false); - pref("browser.startup.homepage_override.mstone", "ignore"); - pref("startup.homepage_welcome_url", ""); - pref("startup.homepage_welcome_url.additional", ""); - pref("browser.sessionstore.resume_from_crash", false); - pref("browser.sessionstore.max_resumed_crashes", 0); - pref("network.captive-portal-service.enabled", false); - pref("network.connectivity-service.enabled", false); - pref("browser.messaging-system.whatsNewPanel.enabled", false); - pref("browser.aboutwelcome.enabled", false); - pref("privacy.popups.showBrowserMessage", false); - ''; - - firefoxWrapped = pkgs.wrapFirefox pkgs.firefox-unwrapped { - extraPolicies = kioskPolicies; - extraPrefsFiles = [ extraPrefs ]; - }; - - firefoxKiosk = pkgs.writeShellScriptBin "firefoxkiosk" '' + chromiumKiosk = pkgs.writeShellScriptBin "chromiumkiosk" '' #!/usr/bin/env bash set -eu @@ -70,12 +32,7 @@ let # Map MAC addresses to specific station IDs case "$MAC" in - "00:e0:4c:46:0b:32") STATION="1" ;; - "00:e0:4c:46:07:26") STATION="2" ;; - "00:e0:4c:46:05:94") STATION="3" ;; - "00:e0:4c:46:07:11") STATION="4" ;; - "00:e0:4c:46:08:02") STATION="5" ;; - "00:e0:4c:46:08:5c") STATION="6" ;; + ${macCases} *) ;; esac @@ -93,31 +50,31 @@ let # Add BrowserID query param if we have one if [ -n "$BROWSER_ID" ]; then if [[ "$URL" == *"?"* ]]; then - URL="$URL&BrowserID=$BROWSER_ID" + URL="$URL&BrowserID=$BROWSER_ID" else - URL="$URL?BrowserID=$BROWSER_ID" + URL="$URL?BrowserID=$BROWSER_ID" fi fi sleep 2 - exec ${firefoxWrapped}/bin/firefox --kiosk "$URL" + exec ${pkgs.chromium}/bin/chromium --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble "$URL" ''; in { - environment.systemPackages = [ firefoxKiosk ]; + environment.systemPackages = [ + pkgs.chromium + chromiumKiosk + ]; - services.xserver.enable = false; - services.seatd.enable = true; - - services.cage = { - enable = true; - user = "engr-ugaif"; - program = "${firefoxKiosk}/bin/firefoxkiosk"; - }; - - systemd.services.cage = { - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; + systemd.user.services.chromium-kiosk = { + description = "Chromium Kiosk"; + wantedBy = [ "graphical-session.target" ]; + partOf = [ "graphical-session.target" ]; + serviceConfig = { + ExecStart = "${chromiumKiosk}/bin/chromiumkiosk"; + Restart = "on-failure"; + Type = "simple"; + }; }; } diff --git a/sw/stateless-kiosk/mac-hostmap.nix b/sw/stateless-kiosk/mac-hostmap.nix new file mode 100644 index 0000000..099b37d --- /dev/null +++ b/sw/stateless-kiosk/mac-hostmap.nix @@ -0,0 +1,27 @@ +# Shared MAC address to station mapping and case builder for stateless-kiosk modules +{ lib }: +let + hostmap = { + "00:e0:4c:46:0b:32" = "1"; + "00:e0:4c:46:07:26" = "2"; + "00:e0:4c:46:05:94" = "3"; + "00:e0:4c:46:07:11" = "4"; + "00:e0:4c:46:08:02" = "5"; + "00:e0:4c:46:08:5c" = "6"; + }; + # macCaseBuilder: builds a shell case statement from a hostmap + # varName: the shell variable to assign + # prefix: optional string to prepend to the value (default: "") + # attrset: attribute set to use (default: hostmap) + macCaseBuilder = { + varName, + prefix ? "", + attrset ? hostmap + }: + lib.concatStringsSep "\n" ( + lib.mapAttrsToList (mac: val: " ${mac}) ${varName}=${prefix}${val} ;;") attrset + ); +in +{ + inherit hostmap macCaseBuilder; +} diff --git a/sw/stateless-kiosk/net.nix b/sw/stateless-kiosk/net.nix index 7f1d222..4ddc05b 100644 --- a/sw/stateless-kiosk/net.nix +++ b/sw/stateless-kiosk/net.nix @@ -28,7 +28,7 @@ netdevs."20-vlan5" = { netdevConfig = { Kind = "vlan"; - Name = "vlan5"; + Name = "vlan5"; }; vlanConfig.Id = 5; }; diff --git a/sw/stateless-kiosk/programs.nix b/sw/stateless-kiosk/programs.nix new file mode 100644 index 0000000..55ffbd9 --- /dev/null +++ b/sw/stateless-kiosk/programs.nix @@ -0,0 +1,7 @@ +{ config, lib, pkgs, ... }: +{ + programs.sway = { + enable = true; + wrapperFeatures.gtk = true; + }; +} diff --git a/sw/stateless-kiosk/services.nix b/sw/stateless-kiosk/services.nix new file mode 100644 index 0000000..ddd6596 --- /dev/null +++ b/sw/stateless-kiosk/services.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: +let + macCaseBuilder = (import ./mac-hostmap.nix { inherit lib; }).macCaseBuilder; + shellCases = macCaseBuilder { + varName = "NEW_HOST"; + prefix = "nix-station"; + }; +in +{ + services.xserver.enable = false; + services.seatd.enable = true; + services.openssh.enable = true; + services.dbus.enable = true; + security.polkit.enable = true; + + services.displayManager = { + autoLogin = { + enable = true; + user = "engr-ugaif"; + }; + + sddm = { + enable = true; + wayland.enable = true; + }; + + defaultSession = "sway"; + }; + + systemd.services.dynamic-hostname = { + description = "Set hostname based on MAC address"; + wantedBy = [ "sysinit.target" ]; + wants = [ "default.target" ]; + after = [ "default.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = pkgs.writeShellScript "dynamic-hostname" '' + set -euo pipefail + + # Pick first non-loopback interface with a MAC + IFACE="$(ls /sys/class/net | grep -v '^lo$' | head -n1)" + MAC="$(cat /sys/class/net/$IFACE/address | tr '[:upper:]' '[:lower:]')" + + case "$MAC" in + ${shellCases} + *) NEW_HOST="nix-station-unregistered" ;; + esac + + ${pkgs.nettools}/bin/hostname "$NEW_HOST" + ''; + }; + }; +}