From 3d3f6053dd0e2a100d38786c2edf8c7b8cc4320d Mon Sep 17 00:00:00 2001 From: batteredbunny Date: Wed, 19 Mar 2025 23:45:29 +0200 Subject: [PATCH] feat: Port qbittorrent changes from upstream --- modules/qbittorrent-nox.nix | 80 ++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/modules/qbittorrent-nox.nix b/modules/qbittorrent-nox.nix index 749c6d2..457ac10 100644 --- a/modules/qbittorrent-nox.nix +++ b/modules/qbittorrent-nox.nix @@ -1,6 +1,7 @@ { config , pkgs , lib +, utils , ... }: let @@ -8,22 +9,21 @@ let in { options.services.qbittorrent-nox = { - enable = lib.mkEnableOption "qbittorrent, BitTorrent client."; + enable = lib.mkEnableOption "qbittorrent, BitTorrent client"; package = lib.mkPackageOption pkgs "qbittorrent-nox" { }; - openFirewall = lib.mkOption { - default = false; - description = "Opens the torreting port"; - }; + openFirewall = lib.mkEnableOption "opening both the webuiPort and torrentPort over TCP in the firewall"; webuiPort = lib.mkOption { - type = lib.types.int; + default = 8080; + type = lib.types.nullOr lib.types.port; description = "the port passed to qbittorrent via `--webui-port`"; }; torrentingPort = lib.mkOption { - type = lib.types.int; + default = null; + type = lib.types.nullOr lib.types.port; description = "the port passed to qbittorrent via `--torrenting-port`"; }; @@ -38,9 +38,37 @@ in default = "qbittorrent"; description = "Group under which qbittorrent runs."; }; + + profileDir = lib.mkOption { + type = lib.types.path; + default = "/var/lib/qBittorrent/"; + description = "the path passed to qbittorrent via --profile."; + }; + extraArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = '' + Extra arguments passed to qbittorrent. See `qbittorrent -h`, or the [source code](https://github.com/qbittorrent/qBittorrent/blob/master/src/app/cmdoptions.cpp), for the available arguments. + ''; + example = [ + "--confirm-legal-notice" + ]; + }; }; config = lib.mkIf cfg.enable { systemd = { + tmpfiles.settings = { + qbittorrent = { + "${cfg.profileDir}/qBittorrent/"."d" = { + mode = "700"; + inherit (cfg) user group; + }; + "${cfg.profileDir}/qBittorrent/config/"."d" = { + mode = "700"; + inherit (cfg) user group; + }; + }; + }; services.qbittorrent-nox = { description = "qbittorrent BitTorrent client"; wants = [ "network-online.target" ]; @@ -52,21 +80,35 @@ in wantedBy = [ "multi-user.target" ]; # Needed for running cross-seed's hook - # /bin/sh -c "curl -XPOST http://localhost:2468/api/webhook --data-urlencode 'name=%N'" + # /bin/sh -c "curl -XPOST http://localhost:2468/api/webhook?apikey=key --data-urlencode 'name=%N'" path = with pkgs; [ curl ]; - # paths: ~/.config/qBittorrent/ and ~/.local/share/qBittorrent/ serviceConfig = { Type = "simple"; User = cfg.user; Group = cfg.group; - ExecStart = "${lib.getExe cfg.package} --webui-port=${toString cfg.webuiPort} --torrenting-port=${toString cfg.torrentingPort}"; - + ExecStart = utils.escapeSystemdExecArgs ( + [ + (lib.getExe cfg.package) + "--profile=${cfg.profileDir}" + ] + ++ lib.optional (cfg.webuiPort != null) "--webui-port=${toString cfg.webuiPort}" + ++ lib.optional (cfg.torrentingPort != null) "--torrenting-port=${toString cfg.torrentingPort}" + ++ cfg.extraArgs + ); TimeoutStopSec = 1800; + + # https://github.com/qbittorrent/qBittorrent/pull/6806#discussion_r121478661 + PrivateTmp = false; + + PrivateNetwork = false; RemoveIPC = true; NoNewPrivileges = true; + PrivateDevices = true; + PrivateUsers = true; + ProtectHome = "yes"; ProtectProc = "invisible"; ProcSubset = "pid"; ProtectSystem = "full"; @@ -93,8 +135,18 @@ in }; }; - networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ - cfg.torrentingPort - ]; + users = { + users = lib.mkIf (cfg.user == "qbittorrent") { + qbittorrent = { + inherit (cfg) group; + isSystemUser = true; + }; + }; + groups = lib.mkIf (cfg.group == "qbittorrent") { qbittorrent = { }; }; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall ( + lib.optional (cfg.torrentingPort != null) cfg.torrentingPort + ); }; }