pkgs: _previousPkgs: { firejailWrap = { package, packageName ? package.meta.mainProgram or (pkgs.lib.getName package), paths ? [ "bin/${packageName}" ], name ? package.name + "-firejailed", args ? [ ], firejail ? "/run/wrappers/bin/firejail", }: pkgs.lib.makeOverridable ( # CompatibilityNote: if .override(overrideArgs) is used # on the wrapping package (eg. if used on programs.firefox.package), # overrideArgs is passed to the wrapped package. overrideArgs: # DesignExplanation: using symlinkJoin instead of package.overrideAttrs # enables to get the wrapped package from the cache as usual. # The main drawback is that the user may have to inherit more attributes. # eg. programs.neovim.package = pkgs.firejailWrap { … } // { inherit (pkgs.neovim-unwrapped) lua; }; pkgs.symlinkJoin { inherit name; meta = package.meta or { }; passthru = package.passthru or { }; paths = [ (package.override overrideArgs) ]; nativeBuildInputs = [ pkgs.makeShellWrapper ]; postBuild = '' # ExplanationNote: /run/wrappers/ is not yet available # hence disable that check in makeShellWrapper. assertExecutable () { true; } for path in ${pkgs.lib.escapeShellArgs paths}; do rm "$out/$path" # CorrectnessNote: in case the wrapping package is called # when building a derivation (eg. in neovim: Generating remote plugin manifest) # /run/wrappers/ does not exist, hence just bypass firejail using a --run. makeShellWrapper \ ${firejail} \ "$out/$path" \ --run "[ -x ${firejail} ] || exec \"${package}/$path\" \"\$@\"" \ --add-flags "\''${FIREJAIL_FLAGS:-}" \ --add-flags "\''${FIREJAIL_FLAGS_${packageName}:-}" \ --add-flags "${pkgs.lib.escapeShellArgs args}" \ --add-flags "${package}/$path" \ --inherit-argv0 done ''; } ) { }; }