Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Add nixos and home-manager modules
to manage flatpaks declaratively.
  • Loading branch information
gmodena committed Oct 22, 2023
1 parent 332e5b4 commit 72346d9
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copied from https://github.com/kclejeune/system/blob/master/.github/workflows/build.yml. Modified.
name: 'system build'
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
runs-on: ${{ matrix.os }}
continue-on-error: true
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v18
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- run: nix flake check
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,63 @@
[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges)

# nix-flatpak
Manage flatpak applications declaratively

Declarative flatpak manager for NixOS inspired by [declarative-flatpak](https://github.com/GermanBread/declarative-flatpak) and nix-darwin's [homebrew](https://github.com/LnL7/nix-darwin/blob/master/modules/homebrew.nix) 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](https://talks.nixcon.org/nixcon-2023/talk/MNUFFP/)
talk at NixCon 2023. I like the idea of managing applications the say way I do
with homebrew on nix-darwin.

`nix-flatpak` follows a [convergent mode](https://flyingcircus.io/blog/thoughts-on-systems-management-methods/) approach to package management (described in [this thread](https://discourse.nixos.org/t/feature-discussion-declarative-flatpak-configuration/26767/2)):
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 lastet version, or allow them to auto update.
For such applications, a convergent approach is a reasonable tradeoff wrt system reproducibility. YMMW.

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.

## Getting Started

Enable flatpak in `configuration.nix`:
```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 looks something like this:

```nix
{
inputs = {
# ...
nix-flatpak.url = "github:gmodena/nix-flatpak/main";
};
outputs = { flatpaks, ... }: {
nixosConfigurations.<host> = nixpkgs.lib.nixosSystem {
modules = [
nix-flatpak.nixosModules.nix-flatpak
./configuration.nix
];
};
};
}
```

Declare packages to install with:
```nix
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.
83 changes: 83 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
description = "Manage flatpak apps declaratively.";

outputs = { self, ... }:
{
nixosModules = { nix-flatpak = import ./modules/nixos.nix; };
homeManagerModules = { nix-flatpak = import ./modules/home-manager.nix; };
};
}
65 changes: 65 additions & 0 deletions modules/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{ cfg, lib, pkgs, ... }:
with lib;
let
cfg = config.services.flatpak;

remoteOptions = { cfg, ... }: {
options = {
name = mkOption {
type = types.str;
description = lib.mdDoc "The remote name";
default = "flathub";
};
location = mkOption {
type = types.str;
description = lib.mdDoc "The remote location";
default = "https://dl.flathub.org/repo/flathub.flatpakrepo";
};
args = mkOption {
type = types.nullOr types.str;
description = "Extra arguments to pass to flatpak remote-add";
default = null;
};
};
};

packageOptions = { cfg, ... }: {
options = {
appId = mkOption {
type = types.str;
description = lib.mdDoc "The fully qualified id of the app to install.";
};

commit = mkOption {
type = types.nullOr types.str;
description = lib.mdDoc "Hash id of the app commit to install";
default = null;
};

origin = mkOption {
type = types.str;
default = "flathub";
description = lib.mdDoc "App repository origin (default: flathub)";
};
};
};


in
{
packages = mkOption {
type = with types; listOf (coercedTo str (appId: { inherit appId; }) (submodule packageOptions));
default = [ ];
description = mkDoc ''
Declares a list of applications to install.
'';
};
remotes = mkOption {
type = with types; listOf (coercedTo str (name: { inherit name location; }) (submodule remoteOptions));
default = [{ name = "flathub"; location = "https://dl.flathub.org/repo/flathub.flatpakrepo"; }];
description = mkDoc ''
Declare a list of flatpak repositories.
'';
};

}
40 changes: 40 additions & 0 deletions modules/home-manager.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{ config, lib, pkgs, osConfig, ... }:
let
cfg = config.services.flatpak;
installation = "user";
in
{

options.services.flatpak = import ./default.nix { inherit cfg lib pkgs; };

config = lib.mkIf osConfig.services.flatpak.enable {
systemd.user.services."flatpak-managed" = {
Unit = {
After = [
"network.target"
];
};
Install = {
WantedBy = [
"default.target"
];
};
Service = {
Type = "oneshot";
ExecStart = "${import ./installer.nix {inherit cfg pkgs; installation = installation; }}";
};
};

home.activation = {
start-service = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
export PATH=${lib.makeBinPath (with pkgs; [ systemd ])}:$PATH
$DRY_RUN_CMD systemctl is-system-running -q && \
systemctl --user start flatpak-managed.service || true
'';
};

xdg.enable = true;
};

}
39 changes: 39 additions & 0 deletions modules/installer.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{ cfg, pkgs, installation ? "system", ... }:

let
flatpakInstallCmd = installation: { appId, origin ? "flathub", commit ? null, ... }: ''
${pkgs.flatpak}/bin/flatpak --${installation} --noninteractive --no-auto-pin install ${origin} ${appId}
${if commit == null
then '' ''
else ''${pkgs.flatpak}/bin/flatpak --${installation} unpdate --commit="${commit}" ${origin} ${appId}
''}'';

flatpakAddRemoteCmd = installation: { name, location, args ? null, ... }: ''
${pkgs.flatpak}/bin/flatpak remote-add --${installation} --if-not-exists ${if args == null then "" else args} ${name} ${location}
'';
flatpakAddRemote = installation: remotes: map (flatpakAddRemoteCmd installation) remotes;
flatpakInstall = installation: packages: map (flatpakInstallCmd installation) packages;

mkFlatpakInstallCmd = installation: packages: builtins.foldl' (x: y: x + y) '''' (flatpakInstall installation packages);
mkFlatpakAddRemoteCmd = installation: remotes: builtins.foldl' (x: y: x + y) '''' (flatpakAddRemote installation remotes);
mkFlatpakInstallScript = installation: pkgs.writeShellScript "flatpak-managed-install" ''
# This script is triggered at build time by a transient systemd unit.
set -eu
# Configure remotes
${mkFlatpakAddRemoteCmd installation cfg.remotes}
# Insall packages
${mkFlatpakInstallCmd installation cfg.packages}
'';
in
pkgs.writeShellScript "flatpak-managed-install" ''
# This script is triggered at build time by a transient systemd unit.
set -eu
# Configure remotes
${mkFlatpakAddRemoteCmd installation cfg.remotes}
# Insall packages
${mkFlatpakInstallCmd installation cfg.packages}
''
23 changes: 23 additions & 0 deletions modules/nixos.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.flatpak;
installation = "system";
in
{
options.services.flatpak = import ./default.nix { inherit cfg lib pkgs; };

config = lib.mkIf config.services.flatpak.enable {
systemd.services."flatpak-managed" = {
wants = [
"network-online.target"
];
wantedBy = [
"multi-user.target"
];
serviceConfig = {
Type = "oneshot";
ExecStart = "${import ./installer.nix {inherit cfg pkgs; installation = installation; }}";
};
};
};
}

0 comments on commit 72346d9

Please sign in to comment.