1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.programs.firejail;
7
8 wrappedBins = pkgs.runCommand "firejail-wrapped-binaries"
9 { preferLocalBuild = true;
10 allowSubstitutes = false;
11 }
12 ''
13 mkdir -p $out/bin
14 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: value:
15 let
16 opts = if builtins.isAttrs value
17 then value
18 else { executable = value; profile = null; extraArgs = []; };
19 args = lib.escapeShellArgs (
20 (optional (opts.profile != null) "--profile=${toString opts.profile}")
21 ++ opts.extraArgs
22 );
23 in
24 ''
25 cat <<_EOF >$out/bin/${command}
26 #! ${pkgs.runtimeShell} -e
27 exec /run/wrappers/bin/firejail ${args} -- ${toString opts.executable} "\$@"
28 _EOF
29 chmod 0755 $out/bin/${command}
30 '') cfg.wrappedBinaries)}
31 '';
32
33in {
34 options.programs.firejail = {
35 enable = mkEnableOption "firejail";
36
37 wrappedBinaries = mkOption {
38 type = types.attrsOf (types.either types.path (types.submodule {
39 options = {
40 executable = mkOption {
41 type = types.path;
42 description = "Executable to run sandboxed";
43 example = literalExpression ''"''${lib.getBin pkgs.firefox}/bin/firefox"'';
44 };
45 profile = mkOption {
46 type = types.nullOr types.path;
47 default = null;
48 description = "Profile to use";
49 example = literalExpression ''"''${pkgs.firejail}/etc/firejail/firefox.profile"'';
50 };
51 extraArgs = mkOption {
52 type = types.listOf types.str;
53 default = [];
54 description = "Extra arguments to pass to firejail";
55 example = [ "--private=~/.firejail_home" ];
56 };
57 };
58 }));
59 default = {};
60 example = literalExpression ''
61 {
62 firefox = {
63 executable = "''${lib.getBin pkgs.firefox}/bin/firefox";
64 profile = "''${pkgs.firejail}/etc/firejail/firefox.profile";
65 };
66 mpv = {
67 executable = "''${lib.getBin pkgs.mpv}/bin/mpv";
68 profile = "''${pkgs.firejail}/etc/firejail/mpv.profile";
69 };
70 }
71 '';
72 description = ''
73 Wrap the binaries in firejail and place them in the global path.
74 </para>
75 <para>
76 You will get file collisions if you put the actual application binary in
77 the global environment and applications started via .desktop files are
78 not wrapped if they specify the absolute path to the binary.
79 '';
80 };
81 };
82
83 config = mkIf cfg.enable {
84 security.wrappers.firejail =
85 { setuid = true;
86 owner = "root";
87 group = "root";
88 source = "${lib.getBin pkgs.firejail}/bin/firejail";
89 };
90
91 environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
92 };
93
94 meta.maintainers = with maintainers; [ peterhoeg ];
95}