From 5d44bc607576b620cd78a1fd7384c2262a9647db Mon Sep 17 00:00:00 2001 From: Vincent Mahnke Date: Thu, 25 Dec 2025 18:13:46 +0100 Subject: [PATCH] Add NixOS kiosk flake and config --- flake.nix | 29 ++++++++++ nixos/kiosk.nix | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 flake.nix create mode 100644 nixos/kiosk.nix diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..27086ff --- /dev/null +++ b/flake.nix @@ -0,0 +1,29 @@ +{ + description = "Kiosk NixOS ISO with Firefox in kiosk mode"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + flake-utils.url = "github:numtide/flake-utils"; + nixos-generators.url = "github:nix-community/nixos-generators"; + }; + + outputs = { self, nixpkgs, flake-utils, nixos-generators }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = import nixpkgs { inherit system; }; + in { + # Build a bootable ISO image using nixos-generators + packages.iso = nixos-generators.nixosGenerate { + inherit pkgs; + format = "iso"; + modules = [ ./nixos/kiosk.nix ]; + }; + + # Expose the NixOS configuration for direct use if desired + nixosConfigurations.kiosk = let + lib = nixpkgs.lib; + in lib.nixosSystem { + system = "x86_64-linux"; + modules = [ ./nixos/kiosk.nix ]; + }; + }); +} diff --git a/nixos/kiosk.nix b/nixos/kiosk.nix new file mode 100644 index 0000000..dad68b9 --- /dev/null +++ b/nixos/kiosk.nix @@ -0,0 +1,140 @@ +{ config, pkgs, lib, ... }: + +{ + ############################################ + # Base system + ############################################ + nixpkgs.hostPlatform = "x86_64-linux"; + system.stateVersion = "24.11"; + + # Simple console-based kiosk using cage (Wayland single-app compositor) + services.xserver.enable = false; # Not using an X11 display manager + + # Autologin to TTY1 as kiosk user + services.getty.autologinUser = "kiosk"; + + # Kiosk user + users.users.kiosk = { + isNormalUser = true; + description = "Kiosk User"; + home = "/home/kiosk"; + extraGroups = [ "wheel" ]; + initialPassword = "kiosk"; + }; + + # Packages required (aligning with the Debian preseed intent) + environment.systemPackages = with pkgs; [ + firefox + cage + curl + unzip + # chromium # available if you want it in addition to Firefox + ]; + + ############################################ + # Firefox policies (preconfigured profile settings) + ############################################ + programs.firefox = { + enable = true; + policies = { + DisableDeveloperTools = true; + BlockAboutAddons = true; + BlockAboutConfig = true; + BlockAboutProfiles = true; + BlockAboutSupport = true; + DisableFirefoxAccounts = true; + DisablePrivateBrowsing = true; + DisableProfileImport = true; + DisableProfileRefresh = true; + DisableSafeMode = true; + DisablePocket = true; + DisableFirefoxScreenshots = true; + DisableSetDesktopBackground = true; + + Homepage = { + URL = "https://mahn.ke"; + Locked = true; + }; + + NewTabPage = { Enabled = false; }; + + # Use a Linux path for downloads in kiosk + DownloadDirectory = { + Path = "/home/kiosk/Downloads"; + Locked = true; + }; + + PromptForDownloadLocation = false; + StartDownloadsInTempDirectory = false; + DisableAppUpdate = true; + + Permissions = { + Camera = "deny"; + Microphone = "deny"; + Location = "deny"; + Notifications = "deny"; + }; + + ShowHomeButton = false; + DisplayMenuBar = false; + DisplayBookmarksToolbar = false; + + # Extension & user messaging controls (per your Debian policy JSON) + UserMessaging = { + ExtensionRecommendations = false; + FeatureRecommendations = false; + UrlbarInterventions = false; + SkipOnboarding = false; + MoreFromMozilla = false; + FirefoxLabs = false; + Locked = false; + }; + + # Install Tampermonkey automatically (Firefox will fetch at runtime). + # Note: AMO URL may change; this is the typical latest channel. + Extensions = { + Install = [ + "https://addons.mozilla.org/firefox/downloads/latest/tampermonkey/latest.xpi" + ]; + }; + }; + + # Helpful preferences to keep Firefox minimal + preferences = { + "browser.fullscreen.autohide" = true; + "browser.shell.checkDefaultBrowser" = false; + "browser.startup.page" = 1; # Start with homepage + }; + }; + + ############################################ + # Kiosk launch behavior (replicates your bash_profile approach) + ############################################ + # Create a bash_profile for the kiosk user that launches cage + firefox + system.activationScripts.kioskBashProfile = lib.stringAfter ["users"] '' + mkdir -p /home/kiosk + chown kiosk:kiosk /home/kiosk + sudo -u kiosk mkdir -p /home/kiosk/.config + cat > /home/kiosk/.bash_profile <<'EOF' +if [ -z "$WAYLAND_DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then + exec ${pkgs.cage}/bin/cage ${pkgs.firefox}/bin/firefox --kiosk https://c3nav.de +fi +EOF + chown kiosk:kiosk /home/kiosk/.bash_profile + ''; + + ############################################ + # Include your userscripts in the image for easy import + ############################################ + environment.etc."kiosk/tampermonkey".source = ./../tampermonkey; + + ############################################ + # Networking & basic services + ############################################ + networking.hostName = "kiosk"; + time.timeZone = "UTC"; + services.openssh.enable = true; # optional, mirrors preseed tasksel ssh-server + + # Keep system simple, disable unneeded DM + services.displayManager.enable = false; +}