-diff --git a/pkgs/os-specific/linux/apparmor/default.nix b/pkgs/os-specific/linux/apparmor/default.nix
-index da8cfac3e07..c6c72cc4e52 100644
---- a/pkgs/os-specific/linux/apparmor/default.nix
-+++ b/pkgs/os-specific/linux/apparmor/default.nix
-@@ -20,8 +20,8 @@
+diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
+index e9b5834dab4..779924a65a8 100644
+--- a/nixos/modules/services/torrent/transmission.nix
++++ b/nixos/modules/services/torrent/transmission.nix
+@@ -7,15 +7,20 @@ let
+ inherit (config.environment) etc;
+ apparmor = config.security.apparmor;
+ rootDir = "/run/transmission";
+- homeDir = "/var/lib/transmission";
+ settingsDir = ".config/transmission-daemon";
+ downloadsDir = "Downloads";
+ incompleteDir = ".incomplete";
+ watchDir = "watchdir";
+- # TODO: switch to configGen.json once RFC0042 is implemented
+- settingsFile = pkgs.writeText "settings.json" (builtins.toJSON cfg.settings);
++ settingsFormat = pkgs.formats.json {};
++ settingsFile = settingsFormat.generate "settings.json" cfg.settings;
+ in
+ {
++ imports = [
++ (mkRenamedOptionModule ["services" "transmission" "port"]
++ ["services" "transmission" "settings" "rpc-port"])
++ (mkAliasOptionModule ["services" "transmission" "openFirewall"]
++ ["services" "transmission" "openPeerPorts"])
++ ];
+ options = {
+ services.transmission = {
+ enable = mkEnableOption ''the headless Transmission BitTorrent daemon.
+@@ -24,48 +29,141 @@ in
+ transmission-remote, the WebUI (http://127.0.0.1:9091/ by default),
+ or other clients like stig or tremc.
+
+- Torrents are downloaded to ${homeDir}/${downloadsDir} by default and are
++ Torrents are downloaded to <xref linkend="opt-services.transmission.home"/>/${downloadsDir} by default and are
+ accessible to users in the "transmission" group'';
+
+- settings = mkOption rec {
+- # TODO: switch to types.config.json as prescribed by RFC0042 once it's implemented
+- type = types.attrs;
+- apply = recursiveUpdate default;
+- default =
+- {
+- download-dir = "${cfg.home}/${downloadsDir}";
+- incomplete-dir = "${cfg.home}/${incompleteDir}";
+- incomplete-dir-enabled = true;
+- watch-dir = "${cfg.home}/${watchDir}";
+- watch-dir-enabled = false;
+- message-level = 1;
+- peer-port = 51413;
+- peer-port-random-high = 65535;
+- peer-port-random-low = 49152;
+- peer-port-random-on-start = false;
+- rpc-bind-address = "127.0.0.1";
+- rpc-port = 9091;
+- script-torrent-done-enabled = false;
+- script-torrent-done-filename = "";
+- umask = 2; # 0o002 in decimal as expected by Transmission
+- utp-enabled = true;
+- };
+- example =
+- {
+- download-dir = "/srv/torrents/";
+- incomplete-dir = "/srv/torrents/.incomplete/";
+- incomplete-dir-enabled = true;
+- rpc-whitelist = "127.0.0.1,192.168.*.*";
+- };
++ settings = mkOption {
+ description = ''
+- Attribute set whose fields overwrites fields in
++ Settings whose options overwrite fields in
+ <literal>.config/transmission-daemon/settings.json</literal>
+- (each time the service starts). String values must be quoted, integer and
+- boolean values must not.
++ (each time the service starts).
+
+ See <link xlink:href="https://github.com/transmission/transmission/wiki/Editing-Configuration-Files">Transmission's Wiki</link>
+- for documentation.
++ for documentation of settings not explicitely covered by this module.
+ '';
++ default = {};
++ type = types.submodule {
++ freeformType = settingsFormat.type;
++ options.download-dir = mkOption {
++ type = types.path;
++ default = "${cfg.home}/${downloadsDir}";
++ description = "Directory where to download torrents.";
++ };
++ options.incomplete-dir = mkOption {
++ type = types.path;
++ default = "${cfg.home}/${incompleteDir}";
++ description = ''
++ When enabled with
++ services.transmission.home
++ <xref linkend="opt-services.transmission.settings.incomplete-dir-enabled"/>,
++ new torrents will download the files to this directory.
++ When complete, the files will be moved to download-dir
++ <xref linkend="opt-services.transmission.settings.download-dir"/>.
++ '';
++ };
++ options.incomplete-dir-enabled = mkOption {
++ type = types.bool;
++ default = true;
++ description = "";
++ };
++ options.message-level = mkOption {
++ type = types.ints.between 0 2;
++ default = 2;
++ description = "Set verbosity of transmission messages.";
++ };
++ options.peer-port = mkOption {
++ type = types.port;
++ default = 51413;
++ description = "The peer port to listen for incoming connections.";
++ };
++ options.peer-port-random-high = mkOption {
++ type = types.port;
++ default = 65535;
++ description = ''
++ The maximum peer port to listen to for incoming connections
++ when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
++ '';
++ };
++ options.peer-port-random-low = mkOption {
++ type = types.port;
++ default = 65535;
++ description = ''
++ The minimal peer port to listen to for incoming connections
++ when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
++ '';
++ };
++ options.peer-port-random-on-start = mkOption {
++ type = types.bool;
++ default = false;
++ description = "Randomize the peer port.";
++ };
++ options.rpc-bind-address = mkOption {
++ type = types.str;
++ default = "127.0.0.1";
++ example = "0.0.0.0";
++ description = ''
++ Where to listen for RPC connections.
++ Use \"0.0.0.0\" to listen on all interfaces.
++ '';
++ };
++ options.rpc-port = mkOption {
++ type = types.port;
++ default = 9091;
++ description = "The RPC port to listen to.";
++ };
++ options.script-torrent-done-enabled = mkOption {
++ type = types.bool;
++ default = false;
++ description = ''
++ Whether to run
++ <xref linkend="opt-services.transmission.settings.script-torrent-done-filename"/>
++ at torrent completion.
++ '';
++ };
++ options.script-torrent-done-filename = mkOption {
++ type = types.nullOr types.path;
++ default = null;
++ description = "Executable to be run at torrent completion.";
++ };
++ options.umask = mkOption {
++ type = types.int;
++ default = 2;
++ description = ''
++ Sets transmission's file mode creation mask.
++ See the umask(2) manpage for more information.
++ Users who want their saved torrents to be world-writable
++ may want to set this value to 0.
++ Bear in mind that the json markup language only accepts numbers in base 10,
++ so the standard umask(2) octal notation "022" is written in settings.json as 18.
++ '';
++ };
++ options.utp-enabled = mkOption {
++ type = types.bool;
++ default = true;
++ description = ''
++ Whether to enable <link xlink:href="http://en.wikipedia.org/wiki/Micro_Transport_Protocol">Micro Transport Protocol (µTP)</link>.
++ '';
++ };
++ options.watch-dir = mkOption {
++ type = types.path;
++ default = "${cfg.home}/${watchDir}";
++ description = "Watch a directory for torrent files and add them to transmission.";
++ };
++ options.watch-dir-enabled = mkOption {
++ type = types.bool;
++ default = false;
++ description = ''Whether to enable the
++ <xref linkend="opt-services.transmission.settings.watch-dir"/>.
++ '';
++ };
++ options.trash-original-torrent-files = mkOption {
++ type = types.bool;
++ default = false;
++ description = ''Whether to delete torrents added from the
++ <xref linkend="opt-services.transmission.settings.watch-dir"/>.
++ '';
++ };
++ };
+ };
+
+ downloadDirPermissions = mkOption {
+@@ -74,31 +172,22 @@ in
+ example = "775";
+ description = ''
+ The permissions set by <literal>systemd.activationScripts.transmission-daemon</literal>
+- on the directories <link linkend="opt-services.transmission.settings">settings.download-dir</link>
+- and <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link>.
++ on the directories <xref linkend="opt-services.transmission.settings.download-dir"/>
++ and <xref linkend="opt-services.transmission.settings.incomplete-dir"/>.
+ Note that you may also want to change
+- <link linkend="opt-services.transmission.settings">settings.umask</link>.
+- '';
+- };
+-
+- port = mkOption {
+- type = types.port;
+- description = ''
+- TCP port number to run the RPC/web interface.
+-
+- If instead you want to change the peer port,
+- use <link linkend="opt-services.transmission.settings">settings.peer-port</link>
+- or <link linkend="opt-services.transmission.settings">settings.peer-port-random-on-start</link>.
++ <xref linkend="opt-services.transmission.settings.umask"/>.
+ '';
+ };
+
+ home = mkOption {
+ type = types.path;
+- default = homeDir;
++ default = "/var/lib/transmission";
+ description = ''
+ The directory where Transmission will create <literal>${settingsDir}</literal>.
+- as well as <literal>${downloadsDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.download-dir</link> is changed,
+- and <literal>${incompleteDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link> is changed.
++ as well as <literal>${downloadsDir}/</literal> unless
++ <xref linkend="opt-services.transmission.settings.download-dir"/> is changed,
++ and <literal>${incompleteDir}/</literal> unless
++ <xref linkend="opt-services.transmission.settings.incomplete-dir"/> is changed.
+ '';
+ };
+
+@@ -119,19 +208,22 @@ in
+ description = ''
+ Path to a JSON file to be merged with the settings.
+ Useful to merge a file which is better kept out of the Nix store
+- because it contains sensible data like <link linkend="opt-services.transmission.settings">settings.rpc-password</link>.
++ because it contains sensible data like
++ <xref linkend="opt-services.transmission.settings.rpc-password"/>.
+ '';
+ default = "/dev/null";
+ example = "/var/lib/secrets/transmission/settings.json";
+ };
+
+- openFirewall = mkEnableOption "opening of the peer port(s) in the firewall";
++ openPeerPorts = mkEnableOption "opening of the peer port(s) in the firewall";
++
++ openRPCPort = mkEnableOption "opening of the RPC port in the firewall";
+
+ performanceNetParameters = mkEnableOption ''tweaking of kernel parameters
+ to open many more connections at the same time.
+
+ Note that you may also want to increase
+- <link linkend="opt-services.transmission.settings">settings.peer-limit-global</link>.
++ <xref linkend="opt-services.transmission.settings.peer-limit-global"/>.
+ And be aware that these settings are quite aggressive
+ and might not suite your regular desktop use.
+ For instance, SSH sessions may time out more easily'';
+@@ -152,36 +244,10 @@ in
+ install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.download-dir}'
+ '' + optionalString cfg.settings.incomplete-dir-enabled ''
+ install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.incomplete-dir}'
++ '' + optionalString cfg.settings.watch-dir-enabled ''
++ install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.watch-dir}'
+ '';
+
+- assertions = [
+- { assertion = builtins.match "^/.*" cfg.home != null;
+- message = "`services.transmission.home' must be an absolute path.";
+- }
+- { assertion = types.path.check cfg.settings.download-dir;
+- message = "`services.transmission.settings.download-dir' must be an absolute path.";
+- }
+- { assertion = types.path.check cfg.settings.incomplete-dir;
+- message = "`services.transmission.settings.incomplete-dir' must be an absolute path.";
+- }
+- { assertion = types.path.check cfg.settings.watch-dir;
+- message = "`services.transmission.settings.watch-dir' must be an absolute path.";
+- }
+- { assertion = cfg.settings.script-torrent-done-filename == "" || types.path.check cfg.settings.script-torrent-done-filename;
+- message = "`services.transmission.settings.script-torrent-done-filename' must be an absolute path.";
+- }
+- { assertion = types.port.check cfg.settings.rpc-port;
+- message = "${toString cfg.settings.rpc-port} is not a valid port number for `services.transmission.settings.rpc-port`.";
+- }
+- # In case both port and settings.rpc-port are explicitely defined: they must be the same.
+- { assertion = !options.services.transmission.port.isDefined || cfg.port == cfg.settings.rpc-port;
+- message = "`services.transmission.port' is not equal to `services.transmission.settings.rpc-port'";
+- }
+- ];
+-
+- services.transmission.settings =
+- optionalAttrs options.services.transmission.port.isDefined { rpc-port = cfg.port; };
+-
+ systemd.services.transmission = {
+ description = "Transmission BitTorrent Service";
+ after = [ "network.target" ] ++ optional apparmor.enable "apparmor.service";
+@@ -226,11 +292,9 @@ in
+ cfg.settings.download-dir
+ ] ++
+ optional cfg.settings.incomplete-dir-enabled
+- cfg.settings.incomplete-dir
+- ++
+- optional cfg.settings.watch-dir-enabled
+- cfg.settings.watch-dir
+- ;
++ cfg.settings.incomplete-dir ++
++ optional (cfg.settings.watch-dir-enabled && cfg.settings.trash-original-torrent-files)
++ cfg.settings.watch-dir;
+ BindReadOnlyPaths = [
+ # No confinement done of /nix/store here like in systemd-confinement.nix,
+ # an AppArmor profile is provided to get a confinement based upon paths and rights.
+@@ -239,8 +303,10 @@ in
+ "/run"
+ ] ++
+ optional (cfg.settings.script-torrent-done-enabled &&
+- cfg.settings.script-torrent-done-filename != "")
+- cfg.settings.script-torrent-done-filename;
++ cfg.settings.script-torrent-done-filename != null)
++ cfg.settings.script-torrent-done-filename ++
++ optional (cfg.settings.watch-dir-enabled && !cfg.settings.trash-original-torrent-files)
++ cfg.settings.watch-dir;
+ # The following options are only for optimizing:
+ # systemd-analyze security transmission
+ AmbientCapabilities = "";
+@@ -307,25 +373,28 @@ in
+ };
+ });
+
+- networking.firewall = mkIf cfg.openFirewall (
+- if cfg.settings.peer-port-random-on-start
+- then
+- { allowedTCPPortRanges =
+- [ { from = cfg.settings.peer-port-random-low;
+- to = cfg.settings.peer-port-random-high;
+- }
+- ];
+- allowedUDPPortRanges =
+- [ { from = cfg.settings.peer-port-random-low;
+- to = cfg.settings.peer-port-random-high;
+- }
+- ];
+- }
+- else
+- { allowedTCPPorts = [ cfg.settings.peer-port ];
+- allowedUDPPorts = [ cfg.settings.peer-port ];
+- }
+- );
++ networking.firewall = mkMerge [
++ (mkIf cfg.openPeerPorts (
++ if cfg.settings.peer-port-random-on-start
++ then
++ { allowedTCPPortRanges =
++ [ { from = cfg.settings.peer-port-random-low;
++ to = cfg.settings.peer-port-random-high;
++ }
++ ];
++ allowedUDPPortRanges =
++ [ { from = cfg.settings.peer-port-random-low;
++ to = cfg.settings.peer-port-random-high;
++ }
++ ];
++ }
++ else
++ { allowedTCPPorts = [ cfg.settings.peer-port ];
++ allowedUDPPorts = [ cfg.settings.peer-port ];
++ }
++ ))
++ (mkIf cfg.openRPCPort { allowedTCPPorts = [ cfg.settings.rpc-port ]; })
++ ];
+
+ boot.kernel.sysctl = mkMerge [
+ # Transmission uses a single UDP socket in order to implement multiple uTP sockets,
+@@ -340,74 +409,57 @@ in
+ # Increase the number of available source (local) TCP and UDP ports to 49151.
+ # Usual default is 32768 60999, ie. 28231 ports.
+ # Find out your current usage with: ss -s
+- "net.ipv4.ip_local_port_range" = "16384 65535";
++ "net.ipv4.ip_local_port_range" = mkDefault "16384 65535";
+ # Timeout faster generic TCP states.
+ # Usual default is 600.
+ # Find out your current usage with: watch -n 1 netstat -nptuo
+- "net.netfilter.nf_conntrack_generic_timeout" = 60;
++ "net.netfilter.nf_conntrack_generic_timeout" = mkDefault 60;
+ # Timeout faster established but inactive connections.
+ # Usual default is 432000.
+- "net.netfilter.nf_conntrack_tcp_timeout_established" = 600;
++ "net.netfilter.nf_conntrack_tcp_timeout_established" = mkDefault 600;
+ # Clear immediately TCP states after timeout.
+ # Usual default is 120.
+- "net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 1;
++ "net.netfilter.nf_conntrack_tcp_timeout_time_wait" = mkDefault 1;
+ # Increase the number of trackable connections.
+ # Usual default is 262144.
+ # Find out your current usage with: conntrack -C
+- "net.netfilter.nf_conntrack_max" = 1048576;
++ "net.netfilter.nf_conntrack_max" = mkDefault 1048576;
+ })
+ ];
+
+ security.apparmor.policies."bin.transmission-daemon".profile = ''
+- include <tunables/global>
+- ${pkgs.transmission}/bin/transmission-daemon {
+- include <abstractions/base>
+- include <abstractions/nameservice>
+- include <abstractions/ssl_certs>
+- include "${pkgs.apparmorRulesFromClosure
+- { name = "transmission-daemon"; }
+- [ pkgs.transmission ]}"
+- include <local/bin.transmission-daemon>
+-
+- r @{PROC}/sys/kernel/random/uuid,
+- r @{PROC}/sys/vm/overcommit_memory,
+- r @{PROC}/@{pid}/environ,
+- r @{PROC}/@{pid}/mounts,
+- rwk /tmp/tr_session_id_*,
+- r /run/systemd/resolve/stub-resolv.conf,
+-
+- r ${pkgs.openssl.out}/etc/**,
+- r ${config.systemd.services.transmission.environment.CURL_CA_BUNDLE},
+-
+- owner rw ${cfg.home}/${settingsDir}/**,
+- rw ${cfg.settings.download-dir}/**,
+- ${optionalString cfg.settings.incomplete-dir-enabled ''
+- rw ${cfg.settings.incomplete-dir}/**,
+- ''}
+- ${optionalString cfg.settings.watch-dir-enabled ''
+- rw ${cfg.settings.watch-dir}/**,
+- ''}
+- profile dirs {
+- rw ${cfg.settings.download-dir}/**,
+- ${optionalString cfg.settings.incomplete-dir-enabled ''
+- rw ${cfg.settings.incomplete-dir}/**,
+- ''}
+- ${optionalString cfg.settings.watch-dir-enabled ''
+- rw ${cfg.settings.watch-dir}/**,
+- ''}
+- }
+-
+- ${optionalString (cfg.settings.script-torrent-done-enabled &&
+- cfg.settings.script-torrent-done-filename != "") ''
+- # Stack transmission_directories profile on top of
+- # any existing profile for script-torrent-done-filename
+- # FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
+- # https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
+- px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
+- ''}
+- }
++ include "${pkgs.transmission.apparmor}/bin.transmission-daemon"
++ '';
++ security.apparmor.includes."local/bin.transmission-daemon" = ''
++ r ${config.systemd.services.transmission.environment.CURL_CA_BUNDLE},
++
++ owner rw ${cfg.home}/${settingsDir}/**,
++ rw ${cfg.settings.download-dir}/**,
++ ${optionalString cfg.settings.incomplete-dir-enabled ''
++ rw ${cfg.settings.incomplete-dir}/**,
++ ''}
++ ${optionalString cfg.settings.watch-dir-enabled ''
++ r${optionalString cfg.settings.trash-original-torrent-files "w"} ${cfg.settings.watch-dir}/**,
++ ''}
++ profile dirs {
++ rw ${cfg.settings.download-dir}/**,
++ ${optionalString cfg.settings.incomplete-dir-enabled ''
++ rw ${cfg.settings.incomplete-dir}/**,
++ ''}
++ ${optionalString cfg.settings.watch-dir-enabled ''
++ r${optionalString cfg.settings.trash-original-torrent-files "w"} ${cfg.settings.watch-dir}/**,
++ ''}
++ }
++
++ ${optionalString (cfg.settings.script-torrent-done-enabled &&
++ cfg.settings.script-torrent-done-filename != null) ''
++ # Stack transmission_directories profile on top of
++ # any existing profile for script-torrent-done-filename
++ # FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
++ # https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
++ px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
++ ''}
+ '';
+- security.apparmor.includes."local/bin.transmission-daemon" = "";
+ };
+
+ meta.maintainers = with lib.maintainers; [ julm ];
+diff --git a/pkgs/applications/networking/p2p/transmission/default.nix b/pkgs/applications/networking/p2p/transmission/default.nix
+index ab4fc0908ba..858b09c9aaa 100644
+--- a/pkgs/applications/networking/p2p/transmission/default.nix
++++ b/pkgs/applications/networking/p2p/transmission/default.nix
+@@ -20,6 +20,7 @@
+ , enableSystemd ? stdenv.isLinux
+ , enableDaemon ? true
+ , enableCli ? true
++, apparmorRulesFromClosure
}:
let
-- apparmor-series = "2.13";
-- apparmor-patchver = "5";
-+ apparmor-series = "3.0";
-+ apparmor-patchver = "0";
- apparmor-version = apparmor-series + "." + apparmor-patchver;
-
- apparmor-meta = component: with stdenv.lib; {
-@@ -33,8 +33,8 @@ let
+@@ -37,6 +38,8 @@ in stdenv.mkDerivation {
+ fetchSubmodules = true;
};
- apparmor-sources = fetchurl {
-- url = "https://launchpad.net/apparmor/${apparmor-series}/${apparmor-version}/+download/apparmor-${apparmor-version}.tar.gz";
-- sha256 = "05x7r99k00r97v1cq2f711lv6yqzhbl8zp1i1c7kxra4v0a2lzk3";
-+ url = "https://launchpad.net/apparmor/${apparmor-series}/${apparmor-series}/+download/apparmor-${apparmor-version}.tar.gz";
-+ sha256 = "0pkm8f619c0ra8kpjmarzl9d409dn4sy0kl6mb92gd0ywlgpbzb6";
- };
++ outputs = [ "out" "apparmor" ];
++
+ cmakeFlags =
+ let
+ mkFlag = opt: if opt then "ON" else "OFF";
+@@ -72,6 +75,30 @@ in stdenv.mkDerivation {
+
+ NIX_LDFLAGS = lib.optionalString stdenv.isDarwin "-framework CoreFoundation";
- aa-teardown = writeShellScript "aa-teardown" ''
-@@ -146,7 +146,7 @@ let
-
- postInstall = ''
- sed -i $out/bin/aa-unconfined -e "/my_env\['PATH'\]/d"
-- for prog in aa-audit aa-autodep aa-cleanprof aa-complain aa-disable aa-enforce aa-genprof aa-logprof aa-mergeprof aa-status aa-unconfined ; do
-+ for prog in aa-audit aa-autodep aa-cleanprof aa-complain aa-disable aa-enforce aa-genprof aa-logprof aa-mergeprof aa-unconfined ; do
- wrapProgram $out/bin/$prog --prefix PYTHONPATH : "$out/lib/${python.libPrefix}/site-packages:$PYTHONPATH"
- done
-
-@@ -156,8 +156,6 @@ let
- makeWrapper ${perl}/bin/perl $out/bin/aa-notify --set PERL5LIB ${libapparmor}/${perl.libPrefix} --add-flags $out/bin/aa-notify-wrapped
-
- substituteInPlace $out/bin/aa-remove-unknown \
-- --replace "/usr/bin/aa-status" "$out/bin/aa-status" \
-- --replace "/sbin/modprobe" "${kmod}/bin/modprobe" \
- --replace "/lib/apparmor/rc.apparmor.functions" "${apparmor-parser}/lib/apparmor/rc.apparmor.functions"
- wrapProgram $out/bin/aa-remove-unknown \
- --prefix PATH : ${lib.makeBinPath [gawk]}
-@@ -190,7 +188,7 @@ let
- prePatch = prePatchCommon;
- postPatch = "cd ./binutils";
- makeFlags = [ "LANGS=" "USE_SYSTEM=1" ];
-- installFlags = [ "DESTDIR=$(out)" "BINDIR=$(out)/bin" ];
-+ installFlags = [ "DESTDIR=$(out)" "BINDIR=$(out)/bin" "SBINDIR=$(out)/bin" ];
-
- inherit doCheck;
-
-@@ -294,7 +292,8 @@ let
- # eg. glibc-2.30/lib/gconv/gconv-modules
- "r $path/lib/**"
- ]
-- }: rootPaths: runCommand "apparmor-closure-rules" {} ''
-+ , name ? ""
-+ }: rootPaths: runCommand "apparmor-closure-rules${optionalString (name != "") "-${name}"}" {} ''
- touch $out
- while read -r path
- do printf >>$out "%s,\n" ${lib.concatMapStringsSep " " (x: "\"${x}\"") (baseRules ++ additionalRules)}
++ postInstall = ''
++ install -D /dev/stdin $apparmor/bin.transmission-daemon <<EOF
++ include <tunables/global>
++ $out/bin/transmission-daemon {
++ include <abstractions/base>
++ include <abstractions/nameservice>
++ include <abstractions/ssl_certs>
++ include "${apparmorRulesFromClosure { name = "transmission-daemon"; } ([
++ curl libevent openssl pcre zlib
++ ] ++ lib.optionals enableSystemd [ systemd ]
++ ++ lib.optionals stdenv.isLinux [ inotify-tools ]
++ )}"
++ r @{PROC}/sys/kernel/random/uuid,
++ r @{PROC}/sys/vm/overcommit_memory,
++ r @{PROC}/@{pid}/environ,
++ r @{PROC}/@{pid}/mounts,
++ rwk /tmp/tr_session_id_*,
++ r /run/systemd/resolve/stub-resolv.conf,
++
++ include <local/bin.transmission-daemon>
++ }
++ EOF
++ '';
++
+ meta = {
+ description = "A fast, easy and free BitTorrent client";
+ longDescription = ''