From 425f00a71dd4cf644400e05093921c9af3431c6c Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 24 Sep 2026 19:13:06 +0200 Subject: [PATCH] perf(deploy): make Electron's GPU flags tunable without a rebuild The kiosk has launched with --disable-gpu AND --disable-software-rasterizer since the first ISO commit (19d43c2). Together those turn off GPU compositing and the SwiftShader fallback, which leaves Chromium rasterizing every pixel on the CPU. On a Bay Trail Atom that is expensive, and it is very likely the largest single contributor to a sluggish UI. Nothing in git ever justified the pair. There is no comment, no issue and no commit message about it; the flags arrived with the original hardware bring-up and were carried through every refactor since. The descriptive config at /etc/bitspire/config.env has even claimed ELECTRON_DISABLE_GPU=false this whole time, contradicting the actual command line. So this looks like bring-up scaffolding rather than a diagnosed workaround, and it is worth re-testing now that the Mesa work gives known-good crocus and iris drivers for all three GPU generations in the fleet. Testing it by rebuilding is the wrong loop. These are remote machines with no one at the screen, a wrong flag is a black display, and each attempt is a large closure copy over WireGuard. So the GPU flags move out of ExecStart into a shell variable read from /var/lib/bitspire/.env: set BITSPIRE_ELECTRON_GPU_FLAGS, restart the unit, look at the panel. A bad value is one edit and a restart away from being undone. Behaviour is unchanged by default. The variable uses ${VAR-default}, not ${VAR:-default}, so an absent line means today's flags while an explicitly empty value means no GPU flags at all, i.e. full acceleration. That distinction is the whole point and is why the .env template ships the line commented out rather than set: a present-but-empty value would silently enable the GPU on every machine that regenerates its .env. The live ISO takes the same launcher via specialArgs, so the ISO and the installed image cannot drift apart on this. Closure is unchanged at 4604MB. --- deploy/nixos/live.nix | 4 ++-- flake.nix | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/deploy/nixos/live.nix b/deploy/nixos/live.nix index c7882cc..878d2b5 100644 --- a/deploy/nixos/live.nix +++ b/deploy/nixos/live.nix @@ -10,7 +10,7 @@ # Does NOT import hardware/upboard.nix (its fileSystems conflict with live boot). # Instead, duplicates only the hardware-relevant kernel modules and GPU config. -{ config, lib, pkgs, pkgs-unstable, nixpkgs, machineModel ? "douro", atm-app, ... }: +{ config, lib, pkgs, pkgs-unstable, nixpkgs, machineModel ? "douro", atm-app, kioskLauncher, ... }: let # Fiat code per machine model (for envTemplate display only) @@ -162,7 +162,7 @@ in Environment = "LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib"; # Electron needs --no-sandbox in the live/testing environment # --enable-logging makes renderer console.log visible in journalctl - ExecStart = lib.mkForce "${pkgs-unstable.electron}/bin/electron --no-sandbox --disable-gpu-sandbox --disable-gpu --disable-software-rasterizer --enable-logging ${atm-app}"; + ExecStart = lib.mkForce "${kioskLauncher}"; # Prevent Electron from consuming all RAM on memory-constrained ATMs MemoryMax = lib.mkForce "1G"; # Disable all security hardening that conflicts with Electron diff --git a/flake.nix b/flake.nix index 194ca55..4a9f720 100644 --- a/flake.nix +++ b/flake.nix @@ -53,6 +53,38 @@ overlays = [ (import rust-overlay) ]; }; + # Kiosk launcher. The GPU-related Electron flags sit in a variable with a + # shell default rather than being baked into ExecStart, so they can be + # changed on a running machine by editing /var/lib/bitspire/.env and + # restarting the unit. No rebuild, no reboot, and a bad value is one edit + # away from being undone. That matters on a box whose screen nobody can + # see: a rebuild-and-pray loop over WireGuard is the wrong tool for + # finding out which flags a given panel tolerates. + # + # The default reproduces exactly what these machines have shipped since + # the first ISO (19d43c2): GPU compositing off AND the software + # rasterizer off, which leaves Chromium rasterizing every pixel on the + # CPU. Nothing in git ever justified that pair. It arrived with the + # original bring-up commit and was carried forward through every + # refactor since, and it is expensive on a Bay Trail Atom. + # + # Values to try in /var/lib/bitspire/.env: + # BITSPIRE_ELECTRON_GPU_FLAGS= full acceleration + # BITSPIRE_ELECTRON_GPU_FLAGS=--disable-gpu no GPU, SwiftShader allowed + # BITSPIRE_ELECTRON_GPU_FLAGS=--use-gl=egl force EGL if GLX misbehaves + # (line absent) the shipped default below + # + # Note `-` and not `:-`. An explicitly EMPTY value means "no GPU flags at + # all", i.e. full acceleration, and must not fall back to the default. + # Unquoted on purpose so the value word-splits into argv. + mkKioskLauncher = atm-app: pkgs.writeShellScript "bitspire-kiosk" '' + default_gpu_flags="--disable-gpu --disable-software-rasterizer" + exec ${pkgs-unstable.electron}/bin/electron \ + --no-sandbox --disable-gpu-sandbox --enable-logging \ + ''${BITSPIRE_ELECTRON_GPU_FLAGS-$default_gpu_flags} \ + ${atm-app} + ''; + # Pure ATM app builder (no --impure needed) mkAtmApp = import ./nix/mkAtmApp.nix { inherit pkgs pkgs-unstable; @@ -81,6 +113,7 @@ inherit system; specialArgs = { inherit pkgs-unstable nixpkgs machineModel atm-app; + kioskLauncher = mkKioskLauncher atm-app; }; modules = [ ./deploy/nixos/live.nix @@ -209,6 +242,14 @@ VITE_SPIRE_SEED= ELECTRON_FORCE_PROD=1 DISPLAY=:0 + # Uncomment to change Electron's GPU flags without a + # rebuild, then `systemctl restart bitspire`. An empty + # value means full GPU acceleration; the line being absent + # means the shipped default (GPU and software rasterizer + # both off). Commented rather than set, because a present + # -but-empty value here would silently enable the GPU on + # every machine that regenerates its .env. + # BITSPIRE_ELECTRON_GPU_FLAGS= '' + pkgs.lib.optionalString (config.services.bitspire.relayUrl != "") '' VITE_RELAY_URL=${config.services.bitspire.relayUrl} '' + pkgs.lib.optionalString (config.services.bitspire.lnbitsServerPubkey != "") '' @@ -224,7 +265,7 @@ serviceConfig = { EnvironmentFile = lib.mkForce "/var/lib/bitspire/.env"; Environment = "LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib"; - ExecStart = lib.mkForce "${pkgs-unstable.electron}/bin/electron --no-sandbox --disable-gpu-sandbox --disable-gpu --disable-software-rasterizer --enable-logging ${atm-app}"; + ExecStart = lib.mkForce "${mkKioskLauncher atm-app}"; MemoryMax = lib.mkForce "1G"; NoNewPrivileges = lib.mkForce false; ProtectSystem = lib.mkForce false;