diff --git a/modules/genebean/home/default.nix b/modules/genebean/home/default.nix index ea0ab66b..2109669e 100644 --- a/modules/genebean/home/default.nix +++ b/modules/genebean/home/default.nix @@ -54,6 +54,7 @@ ./programs/zoom.nix ./programs/wezterm ./programs/zsh.nix + ./services/chromium-kiosk.nix ./services/flatpak.nix ./services/tailscale.nix ]; diff --git a/modules/genebean/home/services/chromium-kiosk.nix b/modules/genebean/home/services/chromium-kiosk.nix new file mode 100644 index 00000000..c4f267c6 --- /dev/null +++ b/modules/genebean/home/services/chromium-kiosk.nix @@ -0,0 +1,53 @@ +{ config, lib, ... }: +let + cfg = config.genebean.services.chromium-kiosk; +in +{ + options.genebean.services.chromium-kiosk = { + enable = lib.mkEnableOption "chromium kiosk pointed at a Home Assistant dashboard"; + + dashboardUrl = lib.mkOption { + type = lib.types.str; + description = "URL chromium opens in --app/--kiosk mode."; + example = "http://192.168.22.22:8123/kiosk-entryway/immich?kiosk"; + }; + + extraCommandLineArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "Extra chromium flags appended after the common kiosk set."; + example = [ "--hide-scrollbars" ]; + }; + + rotate = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "wlr-randr --transform value (e.g. \"90\", \"flipped-90\"). null = no --transform flag."; + }; + + wlrRandrOutput = lib.mkOption { + type = lib.types.str; + default = "HDMI-A-1"; + description = "wlr-randr output name cage's compositor targets."; + }; + }; + + config = lib.mkIf cfg.enable { + programs.chromium = { + enable = true; + commandLineArgs = [ + "--app=${cfg.dashboardUrl}" + "--kiosk" + "--noerrdialogs" + "--disable-infobars" + "--no-first-run" + "--ozone-platform=wayland" + "--enable-features=OverlayScrollbar" + "--start-maximized" + "--force-dark-mode" + "--hide-crash-restore-bubble" + ] + ++ cfg.extraCommandLineArgs; + }; + }; +} diff --git a/modules/genebean/nixos/default.nix b/modules/genebean/nixos/default.nix index cc7cae62..408cb247 100644 --- a/modules/genebean/nixos/default.nix +++ b/modules/genebean/nixos/default.nix @@ -9,6 +9,7 @@ ./programs/onepassword.nix ./programs/thunderbird.nix ./programs/xfce4-terminal.nix + ./services/chromium-kiosk.nix ./services/flatpak.nix ./services/tailscale.nix ]; diff --git a/modules/genebean/nixos/services/chromium-kiosk.nix b/modules/genebean/nixos/services/chromium-kiosk.nix new file mode 100644 index 00000000..6d3a2364 --- /dev/null +++ b/modules/genebean/nixos/services/chromium-kiosk.nix @@ -0,0 +1,69 @@ +{ + config, + lib, + pkgs, + username, + ... +}: +let + cfg = config.home-manager.users.${username}.genebean.services.chromium-kiosk; + wifiInterface = lib.elemAt config.networking.wireless.interfaces 0; +in +{ + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.wlr-randr ]; + + services.cage = { + enable = true; + environment.WLR_LIBINPUT_NO_DEVICES = "1"; # boot up even if no mouse/keyboard connected + program = pkgs.writeShellScript "kiosk.sh" '' + WAYLAND_DISPLAY=wayland-0 wlr-randr --output ${cfg.wlrRandrOutput}${ + lib.optionalString (cfg.rotate != null) " --transform ${cfg.rotate}" + } + /etc/profiles/per-user/${username}/bin/chromium-browser + ''; + user = username; + }; + + systemd.services = { + # cage-tty1 already Conflicts=getty@tty1.service (set by upstream's + # cage module) to stop both fighting over the same TTY, but that + # alone doesn't prevent getty@tty1 from being reintroduced later. + # Confirmed on hardware: NixOS's activation reactivates TTY-related + # units on every `switch` and (re)starts getty@tty1.service + # regardless of it showing "disabled" - the Conflicts= then kills + # cage-tty1 as a side effect, and nothing re-triggers it afterward + # (WantedBy=graphical.target doesn't get re-evaluated once that + # target's already reached), leaving the kiosk dark until a manual + # restart. Masking getty@tty1 outright - the standard practice for + # a TTY a compositor owns exclusively - removes the conflict at its + # source... except getty@.service's own upstream unit carries + # Alias=autovt@%i.service, so masking the getty@tty1 name alone + # doesn't stop systemd resolving the SAME underlying unit via its + # autovt@tty1 alias instead - confirmed on hardware, masking only + # getty@tty1 still left autovt@tty1.service starting at the exact + # moment cage-tty1 died. Both names need masking. + "autovt@tty1".enable = false; + + cage-tty1 = { + # Upstream's cage module sets restartIfChanged = false, presumably + # to avoid yanking an interactive desktop session out from under + # someone mid `nixos-rebuild switch`. That caution doesn't apply to + # a kiosk - confirmed on hardware that without this override, a + # config change (e.g. a new dashboard URL) requires a manual + # `systemctl restart cage-tty1` (or a reboot) to actually take + # effect, since the switch itself silently leaves the old + # chromium/cage instance running. + restartIfChanged = lib.mkForce true; + wants = [ + "wpa_supplicant-${wifiInterface}.service" + "network-online.target" + ]; + }; + + # Masked alongside its autovt@tty1 alias above - see that entry's + # comment for why both names are needed. + "getty@tty1".enable = false; + }; + }; +} diff --git a/modules/hosts/nixos/kiosk-entryway/default.nix b/modules/hosts/nixos/kiosk-entryway/default.nix index ff2099ad..332299c0 100644 --- a/modules/hosts/nixos/kiosk-entryway/default.nix +++ b/modules/hosts/nixos/kiosk-entryway/default.nix @@ -19,10 +19,6 @@ "ext4" ]; - environment.systemPackages = with pkgs; [ - wlr-randr - ]; - fonts = { fontconfig = { enable = true; @@ -60,21 +56,6 @@ ]; services = { - cage = - let - kioskProgram = pkgs.writeShellScript "kiosk.sh" '' - WAYLAND_DISPLAY=wayland-0 wlr-randr --output HDMI-A-1 - /etc/profiles/per-user/gene/bin/chromium-browser - ''; - in - { - enable = true; - program = kioskProgram; - user = "gene"; - environment = { - WLR_LIBINPUT_NO_DEVICES = "1"; # boot up even if no mouse/keyboard connected - }; - }; prometheus.exporters.node = { enable = true; enabledCollectors = [ @@ -107,13 +88,6 @@ }; }; - systemd.services.cage-tty1 = { - wants = [ - "wpa_supplicant-wlp3s0.service" - "network-online.target" - ]; - }; - users.users.${username} = { isNormalUser = true; description = "Gene Liverman"; diff --git a/modules/hosts/nixos/kiosk-entryway/home-gene.nix b/modules/hosts/nixos/kiosk-entryway/home-gene.nix index 8ff51f92..d453d701 100644 --- a/modules/hosts/nixos/kiosk-entryway/home-gene.nix +++ b/modules/hosts/nixos/kiosk-entryway/home-gene.nix @@ -1,23 +1,9 @@ { home.stateVersion = "24.11"; - programs = { - chromium = { - enable = true; - commandLineArgs = [ - "--app=http://192.168.22.22:8123/kiosk-entryway/immich?kiosk" - "--kiosk" - "--noerrdialogs" - "--disable-infobars" - "--no-first-run" - "--ozone-platform=wayland" - "--enable-features=OverlayScrollbar" - "--start-maximized" - "--force-dark-mode" - "--hide-crash-restore-bubble" - "--hide-scrollbars" - ]; - }; + genebean.services.chromium-kiosk = { + enable = true; + dashboardUrl = "http://192.168.22.22:8123/kiosk-entryway/immich?kiosk"; + extraCommandLineArgs = [ "--hide-scrollbars" ]; }; - } diff --git a/modules/hosts/nixos/kiosk-gene-desk/default.nix b/modules/hosts/nixos/kiosk-gene-desk/default.nix index ac031dd1..2f0043ed 100644 --- a/modules/hosts/nixos/kiosk-gene-desk/default.nix +++ b/modules/hosts/nixos/kiosk-gene-desk/default.nix @@ -35,7 +35,6 @@ environment.systemPackages = with pkgs; [ libraspberrypi raspberrypi-eeprom - wlr-randr ]; hardware = { @@ -86,21 +85,6 @@ ]; services = { - cage = - let - kioskProgram = pkgs.writeShellScript "kiosk.sh" '' - WAYLAND_DISPLAY=wayland-0 wlr-randr --output HDMI-A-1 --transform 90 - /etc/profiles/per-user/gene/bin/chromium-browser - ''; - in - { - enable = true; - program = kioskProgram; - user = "gene"; - environment = { - WLR_LIBINPUT_NO_DEVICES = "1"; # boot up even if no mouse/keyboard connected - }; - }; prometheus.exporters.node = { enable = true; inherit (config.genebean.ports.node-exporter) port; @@ -182,13 +166,6 @@ }; }; - systemd.services.cage-tty1 = { - wants = [ - "wpa_supplicant-wlan0.service" - "network-online.target" - ]; - }; - users.users.${username} = { isNormalUser = true; description = "Gene Liverman"; diff --git a/modules/hosts/nixos/kiosk-gene-desk/home-gene.nix b/modules/hosts/nixos/kiosk-gene-desk/home-gene.nix index 8410f739..e56125e9 100644 --- a/modules/hosts/nixos/kiosk-gene-desk/home-gene.nix +++ b/modules/hosts/nixos/kiosk-gene-desk/home-gene.nix @@ -1,25 +1,15 @@ { home.stateVersion = "24.11"; - genebean.services.tailscale.enable = true; - - programs = { - chromium = { + genebean.services = { + chromium-kiosk = { enable = true; - commandLineArgs = [ - "--app=http://192.168.22.22:8123/kiosk-gene-desk/immich?kiosk" - "--kiosk" - "--noerrdialogs" - "--disable-infobars" - "--no-first-run" - "--ozone-platform=wayland" - "--enable-features=OverlayScrollbar" - "--start-maximized" - "--force-dark-mode" - "--hide-crash-restore-bubble" - ]; + dashboardUrl = "http://192.168.22.22:8123/kiosk-gene-desk/immich?kiosk"; + rotate = "90"; }; - zsh.history.path = "/tmp/zsh_history_gene"; # needed becaues of read only fs + tailscale.enable = true; }; + programs.zsh.history.path = "/tmp/zsh_history_gene"; # needed becaues of read only fs + }