-
-
Notifications
You must be signed in to change notification settings - Fork 19.9k
Flatpak: NixOS-integrated Flatpak package management #347605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ea9ac74
406bbf1
fd3960b
27dcd43
35e0c78
6f3177c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,3 @@ | ||
| # flatpak service. | ||
| { | ||
| config, | ||
| lib, | ||
|
|
@@ -8,8 +7,49 @@ | |
|
|
||
| let | ||
| cfg = config.services.flatpak; | ||
| in | ||
|
|
||
| flatpakCommand = "${cfg.package}/bin/flatpak"; | ||
|
|
||
| manageFlatpaks = pkgs.writeShellScript "manage-flatpaks" '' | ||
| set -eou pipefail | ||
|
|
||
| ${lib.optionalString (cfg.remote != null) '' | ||
| if ! ${flatpakCommand} remotes | grep -q "^${cfg.remote.name}"; then | ||
| echo "Adding Flatpak remote: ${cfg.remote.name}" | ||
| ${flatpakCommand} remote-add --if-not-exists "${cfg.remote.name}" "${cfg.remote.url}" | ||
| else | ||
| echo "Flatpak remote already exists: ${cfg.remote.name}" | ||
| fi | ||
| ''} | ||
|
|
||
| echo "Installing specified Flatpak packages..." | ||
| for pkg in ${toString cfg.packages}; do | ||
| if ! ${flatpakCommand} info "$pkg" &>/dev/null; then | ||
| echo "Installing Flatpak package: $pkg" | ||
| ${flatpakCommand} install --assumeyes "$pkg" | ||
| else | ||
| echo "Flatpak package already installed: $pkg" | ||
| fi | ||
| done | ||
|
|
||
| ${lib.optionalString cfg.removeUnmanagedPackages '' | ||
| echo "Removing unmanaged Flatpak packages..." | ||
| installed_pkgs=$(${flatpakCommand} list --app --columns=application) | ||
| for pkg in $installed_pkgs; do | ||
| if ! echo "${toString cfg.packages}" | grep -q "$pkg"; then | ||
| echo "Removing Flatpak package: $pkg" | ||
| ${flatpakCommand} uninstall --assumeyes "$pkg" | ||
| fi | ||
| done | ||
| ''} | ||
|
|
||
| ${lib.optionalString cfg.update.duringBuild '' | ||
| echo "Updating all Flatpak packages..." | ||
| ${flatpakCommand} update --assumeyes | ||
| ''} | ||
| ''; | ||
|
|
||
| in | ||
| { | ||
| meta = { | ||
| doc = ./flatpak.md; | ||
|
|
@@ -22,12 +62,90 @@ in | |
| enable = lib.mkEnableOption "flatpak"; | ||
|
|
||
| package = lib.mkPackageOption pkgs "flatpak" { }; | ||
|
|
||
| packages = lib.mkOption { | ||
| type = lib.types.listOf lib.types.str; | ||
| default = [ ]; | ||
| example = [ | ||
| "org.blender.Blender" | ||
| "net.ankiweb.Anki" | ||
| ]; | ||
| description = "List of Flatpak packages to install or update."; | ||
| }; | ||
|
|
||
| removeUnmanagedPackages = lib.mkOption { | ||
| type = lib.types.bool; | ||
| default = false; | ||
| description = "Whether to remove Flatpak packages not listed in 'packages'."; | ||
| }; | ||
|
|
||
| update = { | ||
| auto = { | ||
| enable = lib.mkOption { | ||
| type = lib.types.bool; | ||
| default = false; | ||
| description = "Whether to automatically update Flatpak packages."; | ||
| }; | ||
| onCalendar = lib.mkOption { | ||
| type = lib.types.nullOr lib.types.str; | ||
| default = null; | ||
| example = "weekly"; | ||
| description = '' | ||
| When to perform automatic updates. Uses systemd calendar format. If null, no timer will be created. | ||
| See systemd.time for more information on the calendar event syntax. | ||
| ''; | ||
| }; | ||
| }; | ||
| duringBuild = lib.mkOption { | ||
| type = lib.types.bool; | ||
| default = false; | ||
| description = "Whether to update Flatpak packages during system rebuild."; | ||
| }; | ||
| }; | ||
|
Comment on lines
+99
to
+104
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I’m not wrong, this option is wrongly named and IMO also does currently not do what you probably intended to do.
If the second point is unattended, a check needs to implemented to only execute the update when the config is actually switched. In my own configs, I have an example activationScript which is only executed on switches, see this line. |
||
|
|
||
| remotes = lib.mkOption { | ||
| type = lib.types.listOf ( | ||
| lib.types.submodule { | ||
| options = { | ||
| name = lib.mkOption { | ||
| type = lib.types.str; | ||
| description = "Name of the Flatpak remote."; | ||
| }; | ||
| url = lib.mkOption { | ||
| type = lib.types.str; | ||
| description = "URL of the Flatpak remote."; | ||
| }; | ||
| }; | ||
| } | ||
| ); | ||
| default = [ | ||
| { | ||
| name = "flathub"; | ||
| url = "https://flathub.org/repo/flathub.flatpakrepo"; | ||
| } | ||
| ]; | ||
| example = [ | ||
| { | ||
| name = "flathub"; | ||
| url = "https://flathub.org/repo/flathub.flatpakrepo"; | ||
| } | ||
| { | ||
| name = "gnome"; | ||
| url = "https://sdk.gnome.org/repo/flatpak/gnome-nightly.flatpakrepo"; | ||
| } | ||
| ]; | ||
| description = "List of Flatpak remotes to add. By default, includes Flathub."; | ||
| }; | ||
|
|
||
| removeUnmanagedRemotes = lib.mkOption { | ||
| type = lib.types.bool; | ||
| default = false; | ||
| description = "Whether to remove Flatpak remotes not listed in 'remotes'."; | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| ###### implementation | ||
| config = lib.mkIf cfg.enable { | ||
|
|
||
| assertions = [ | ||
| { | ||
| assertion = (config.xdg.portal.enable == true); | ||
|
|
@@ -54,6 +172,72 @@ in | |
| "/var/lib/flatpak/exports" | ||
| ]; | ||
|
|
||
| # Activation script for installation and optionally updating during build | ||
| system.activationScripts.flatpak-setup = '' | ||
|
zyhe16 marked this conversation as resolved.
|
||
| set -eou pipefail | ||
|
|
||
| # Get list of configured remote names | ||
| configured_remotes="" | ||
| for remote in ${toString cfg.remotes}; do | ||
| remote_name=$(echo $remote | jq -r .name) | ||
| configured_remotes="$configured_remotes $remote_name" | ||
| done | ||
|
|
||
| ${lib.optionalString cfg.removeUnmanagedRemotes '' | ||
| # Remove remotes that are not in the config | ||
| for existing_remote in $(${flatpakCommand} remotes | cut -f1); do | ||
| if ! echo "$configured_remotes" | grep -q " $existing_remote "; then | ||
| echo "Removing unconfigured Flatpak remote: $existing_remote" | ||
| ${flatpakCommand} remote-delete --force "$existing_remote" | ||
| fi | ||
| done | ||
| ''} | ||
|
|
||
| # Add or update configured remotes | ||
| for remote in ${toString cfg.remotes}; do | ||
| remote_name=$(echo $remote | jq -r .name) | ||
| remote_url=$(echo $remote | jq -r .url) | ||
| if ! ${flatpakCommand} remotes | grep -q "^$remote_name"; then | ||
| echo "Adding Flatpak remote: $remote_name" | ||
| ${flatpakCommand} remote-add --if-not-exists "$remote_name" "$remote_url" | ||
| else | ||
| echo "Flatpak remote already exists: $remote_name" | ||
| # Update the remote URL in case it changed | ||
| ${flatpakCommand} remote-modify --url "$remote_url" "$remote_name" | ||
| fi | ||
| done | ||
|
|
||
| echo "Installing specified Flatpak packages..." | ||
| ${manageFlatpaks} | ||
| ''; | ||
|
|
||
| # Systemd service for automatic updates | ||
| systemd.services.flatpak-update = lib.mkIf cfg.update.auto.enable { | ||
| description = "Flatpak package updates"; | ||
| wantedBy = [ "multi-user.target" ]; | ||
| after = [ "network-online.target" ]; | ||
| wants = [ "network-online.target" ]; | ||
| path = [ cfg.package ]; | ||
| script = '' | ||
| ${flatpakCommand} update --assumeyes | ||
| ''; | ||
| serviceConfig = { | ||
| Type = "oneshot"; | ||
| RemainAfterExit = true; | ||
| }; | ||
| }; | ||
|
|
||
| systemd.timers.flatpak-update = | ||
| lib.mkIf (cfg.update.auto.enable && cfg.update.auto.onCalendar != null) | ||
| { | ||
| wantedBy = [ "timers.target" ]; | ||
| timerConfig = { | ||
| OnCalendar = cfg.update.auto.onCalendar; | ||
| Persistent = true; | ||
| Unit = "flatpak-update.service"; | ||
| }; | ||
| }; | ||
|
|
||
| # It has been possible since https://github.com/flatpak/flatpak/releases/tag/1.3.2 | ||
| # to build a SELinux policy module. | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.