{ ... }: { flake.nixosModules.systemFlatpak = { config, lib, pkgs, ... }: let cfg = config.chiasson.system.flatpak; flathubForSystem = lib.filter ( app: if lib.elem app cfg.flathub.x86Only then pkgs.stdenv.hostPlatform.system == "x86_64-linux" else true ) cfg.flathub.appIds; allowedAppIds = cfg.flathub.appIds ++ cfg.unmanaged.appIds; # Bump in Nix when allowlists change; used to skip slow `flatpak update` / `uninstall --unused` on no-op rebuilds. declarativeHash = builtins.hashString "sha256" ( lib.concatStringsSep "\n" ( [ "allowed" ] ++ lib.sort lib.lessThan allowedAppIds ++ [ "flathub" ] ++ lib.sort lib.lessThan flathubForSystem ) ); stateFile = "/var/lib/nixos/flatpak-declarative.hash"; in { options.chiasson.system.flatpak = { enable = lib.mkEnableOption '' System Flatpak (`services.flatpak`) plus an activation script: Flathub remote, allowlisted apps, and removals for anything else. User Flatpak stays in Home Manager. ''; runHeavyMaintenanceEverySwitch = lib.mkOption { type = lib.types.bool; default = false; description = '' When false (default), `flatpak update` and `flatpak uninstall --unused` run only if the allowlists changed (hash in `/var/lib/nixos/flatpak-declarative.hash`). Remotes, removals, and per-app `install` still run every activation. True = full update/unused every switch. ''; }; flathub.appIds = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "Flathub app IDs to install system-wide."; }; flathub.x86Only = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "Subset of `flathub.appIds` only installed on x86_64-linux."; }; unmanaged.appIds = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ "com.hypixel.HytaleLauncher" ]; description = '' Installed from elsewhere (not Flathub); never auto-installed and never removed by the script. ''; }; }; config = lib.mkIf cfg.enable { services.flatpak.enable = true; system.activationScripts.flatpakManagement = { text = '' STATE_FILE=${lib.escapeShellArg stateFile} WANT_HASH=${lib.escapeShellArg declarativeHash} HEAVY=${if cfg.runHeavyMaintenanceEverySwitch then "1" else "0"} mkdir -p /var/lib/nixos # Never remote-delete flathub here — interactive and breaks unattended rebuilds. ${pkgs.flatpak}/bin/flatpak --system remote-add --if-not-exists flathub \ https://dl.flathub.org/repo/ || true ${pkgs.flatpak}/bin/flatpak --system remote-modify flathub \ --url=https://dl.flathub.org/repo/ 2>/dev/null || true allowed=( ${lib.concatStringsSep " " (map lib.escapeShellArg allowedAppIds)} ) installedFlatpaks=$(${pkgs.flatpak}/bin/flatpak --system list --app --columns=application) for installed in $installedFlatpaks; do keep=0 for a in "''${allowed[@]}"; do if [ "$installed" = "$a" ]; then keep=1 break fi done if [ "$keep" -eq 0 ]; then echo "flatpak: removing $installed (not in allowed list)." ${pkgs.flatpak}/bin/flatpak --system uninstall -y --noninteractive "$installed" fi done for app in ${lib.escapeShellArgs flathubForSystem}; do echo "flatpak: ensuring $app (Flathub)." if ! ${pkgs.flatpak}/bin/flatpak --system install -y --noninteractive flathub "$app"; then echo "flatpak: WARN failed to install $app (skip)." >&2 fi done run_heavy=0 if [ "$HEAVY" -eq 1 ]; then run_heavy=1 elif [ ! -f "$STATE_FILE" ] || [ "$(cat "$STATE_FILE")" != "$WANT_HASH" ]; then run_heavy=1 fi if [ "$run_heavy" -eq 1 ]; then ${pkgs.flatpak}/bin/flatpak --system uninstall --unused -y --noninteractive || true ${pkgs.flatpak}/bin/flatpak --system update -y --noninteractive || true printf '%s' "$WANT_HASH" > "$STATE_FILE" else echo "flatpak: allowlists unchanged — skipping update and uninstall --unused." fi ''; }; }; }; }