Skip to content

gmodena/nix-flatpak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

system build

nix-flatpak

Declarative flatpak manager for NixOS inspired by declarative-flatpak and nix-darwin's homebrew module. NixOs and home-manager modules are provided for system wide or user flatpaks installation.

Background

This repository contains experimental code inspired by Martin Wimpress' Blending NixOS with Flathub for friends and family talk at NixCon 2023. I like the idea of managing applications the same way I do with homebrew on nix-darwin.

nix-flatpak follows a convergent mode approach to package management (described in this thread): the target system state description is not exhaustive, and there's room for divergence across builds and rollbacks. For a number of desktop application I want to be able to track the latest version, or allow them to auto update. For such applications, a convergent approach is a reasonable tradeoff wrt system reproducibility. YMMV.

Flatpak applications are installed by systemd oneshot service triggered at system activation. Depending on the number of applications to install, this could increase activation time significantly.

Releases

This project is released as a flake, and is published on flakehub.

Manual installation

Releases are tagged with semantic versioning. Versions below 1.0.0 are considered early, development, releases. Users can track a version by passing its tag as ref

...
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=v0.4.1";
...

The main branch is considered unstable, and might break installs.

Getting Started

Enable flatpak in configuration.nix:

services.flatpak.enable = true;

Import the module (nixosModules.nix-flatpak or homeManagerModules.nix-flatpak). Using flake, installing nix-flatpak as a NixOs module would look something like this:

{
  inputs = {
    # ...
    nix-flatpak.url = "github:gmodena/nix-flatpak"; # unstable branch. Use github:gmodena/nix-flatpak/?ref=<tag> to pin releases.
  };

  outputs = { nix-flatpak, ... }: {
    nixosConfigurations.<host> = nixpkgs.lib.nixosSystem {
      modules = [
        nix-flatpak.nixosModules.nix-flatpak

        ./configuration.nix
      ];
    };
  };
}

See flake.nix in testing-base for examples of setting up nix-flatpak as a NixOs and HomeManager module.

Notes on HomeManager

Depending on how config and inputs are derived homeManagerModules import can be flaky. Here's an example of how homeManagerModules is imported on my nixos systems config in modules/home-manager/desktop/nixos/default.nix. flake-inputs is a special extra arg set in the repo flake.nix mkNixosConfiguration.

Remotes

By default nix-flatpak will add the flathub remote. Remotes can be manually configured via the services.flatpak.remotes option:

services.flatpak.remotes = [{
  name = "flathub-beta"; location = "https://flathub.org/beta-repo/flathub-beta.flatpakrepo";
}];

Note that this declaration will override the default remote config value (flathub). If you want to keep using flathub, you should explicitly declare it in the services.flatpak.remotes option.

Alternatively, it is possible to merge declared remotes with the default one with lib.mkDefaultOption.

  services.flatpak.remotes = lib.mkOptionDefault [{
    name = "flathub-beta";
    location = "https://flathub.org/beta-repo/flathub-beta.flatpakrepo";
  }];

Packages

Declare packages to install with:

  services.flatpak.packages = [
    { appId = "com.brave.Browser"; origin = "flathub";  }
    "com.obsproject.Studio"
    "im.riot.Riot"
  ];

You can pin a specific commit setting commit=<hash> attribute.

Rebuild your system (or home-manager) for changes to take place.

Flatpakref files

Flatpakref files can be installed by setting the flatpakref attribute to :

  services.flatpak.packages = [
    { flatpakref = "<uri>"; sha256="<hash>"; }
  ];

A sha256 hash is required for the flatpakref file. This can be generated with nix-prefetch-url <uri>. Omitting the sha256 attribute will require an impure evaluation of the flake.

When installing an application from a flatpakref, the application remote will be determined as follows:

  1. If the packageOptions contains an origin, use that as the label for the remote URL.
  2. If the package does not specify an origin, use the remote name suggested by the flatpakref (SuggestRemoteName).
  3. If neither the package sets an origin nor the flatpakref suggests a remote name, sanitize the application Name.
Unmanaged packages and remotes

By default nix-flatpak will only manage (install/uninstall/update) packages declared in the services.flatpak.packages and repositories declared in services.flatpak.remotes. Flatpak packages and repositories installed by the command line of app stores won't be affected.

Set services.flatpak.uninstallUnmanaged = true to alter this behaviour, and have nix-flatpak manage the lifecycle of all flatpaks packages and repositories.

Note that services.flatpak.uninstallUnmanaged will only affect a given system of user installation target. If nix-flatpak is installed as a HomeManager module all packages/remotes will be managed in a user installation. Packages/remotes installed system-wide won't be affected by services.flatpak.uninstallUnmanaged.

Similarly, when nix-flatpak is installed as a NixOs module, only system-wide config will be affected.

Updates

Set

services.flatpak.update.onActivation = true;

to enable updates at system activation. The default is false so that repeated invocations of nixos-rebuild switch are idempotent. Applications pinned to a specific commit hash will not be updated.

Periodic updates can be enabled by setting:

services.flatpak.update.auto = {
  enable = true;
  onCalendar = "weekly"; # Default value
};

Auto updates trigger on system activation.

Under the hood, updates are scheduled by realtime systemd timers. onCalendar accepts systemd's update.auto.onCalendar expressions. Timers are persisted across sleep / resume cycles. See https://wiki.archlinux.org/title/systemd/Timers for more information.

Storage

Flatpaks are stored out of nix store at /var/lib/flatpak and ${HOME}/.local/share/flatpak/ for system (nixosModules) and user (homeManagerModules) installation respectively. Flatpaks installation are not generational: upon a system rebuild and rollbacks, changes in packages declaration will result in downloading applications anew.

Keeping flatpaks and nix store orthogonal is an explicit design choice, dictate by my use cases:

  1. I want to track the latest version of all installed applications.
  2. I am happy to trade network for storage.

YMMV.

If you need generational builds, declarative-flatpak might be a better fit.

Overrides

Package overrides can be declared via services.flatpak.overrides. Following is a usage example:

{
  services.flatpak.overrides = {
    global = {
      # Force Wayland by default
      Context.sockets = ["wayland" "!x11" "!fallback-x11"];

      Environment = {
        # Fix un-themed cursor in some Wayland apps
        XCURSOR_PATH = "/run/host/user-share/icons:/run/host/share/icons";

        # Force correct theme for some GTK apps
        GTK_THEME = "Adwaita:dark";
      };
    };

    "com.visualstudio.code".Context = {
      filesystems = [
        "xdg-config/git:ro" # Expose user Git config
        "/run/current-system/sw/bin:ro" # Expose NixOS managed software
      ];
      sockets = [
        "gpg-agent" # Expose GPG agent
        "pcsc" # Expose smart cards (i.e. YubiKey)
      ];
    };

    "org.onlyoffice.desktopeditors".Context.sockets = ["x11"]; # No Wayland support
  };
}

Known issues

A couple of things to be aware of when working with nix-flatpak.

Infinte recusion in home-manager imports

Users have reported an infinite recursion stacktrace when importing an home-manager module outside of where home-manager itself was imported.

To work around this issue, you should avoid nesting home-manager modules. This means that when you are structuring your configuration, make sure that you do not have home-manager modules imported within each other in a way that could lead to circular imports.

You can follow the discussions and updates on issue #25 to stay informed about any resolutions or workarounds.