Skip to content

Commit

Permalink
draft
Browse files Browse the repository at this point in the history
  • Loading branch information
fsnkty committed Feb 17, 2024
1 parent e520c76 commit 35bc83d
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
./services/torrent/rtorrent.nix
./services/torrent/transmission.nix
./services/torrent/torrentstream.nix
./services/torrent/qbittorrent.nix
./services/tracing/tempo.nix
./services/ttys/getty.nix
./services/ttys/gpm.nix
Expand Down
228 changes: 228 additions & 0 deletions nixos/modules/services/torrent/qbittorrent.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.qbittorrent;
inherit (lib) literalExpression;
inherit (lib.types) str unspecified;
inherit (lib.meta) getExe maintainers;
inherit (lib.options) mkEnableOption mkOption mkPackageOption;
inherit (lib.modules) mkIf;

inherit (builtins) concatStringsSep isAttrs;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.strings) escape;
inherit (lib.generators) toINI mkKeyValueDefault mkValueStringDefault;
gendeepINI = toINI {
mkKeyValue =
let
sep = "=";
in
k: v:
if isAttrs v then
concatStringsSep "\n" (
mapAttrsToList (k2: v2: "${escape [ sep ] "${k}\\${k2}"}${sep}${mkValueStringDefault { } v2}") v
)
else
mkKeyValueDefault { } sep k v;
};
in
{
options.services.qbittorrent = {
enable = mkEnableOption "qbittorrent, BitTorrent client.";

package = mkPackageOption pkgs "qbittorrent-nox" { };

openFirewall = mkEnableOption "Opens the default webport and if defined the serverConfig's set ports.";

user = mkOption {
type = str;
default = "qbittorrent";
description = "User account under which qbittorrent runs.";
};

group = mkOption {
type = str;
default = "qbittorrent";
description = "Group under which qbittorrent runs.";
};

profileDir = mkOption {
type = str;
default = "/var/lib/qBittorrent/";
description = "the path passed to qbittorrent via --profile.";
};

serverConfig = mkOption {
description = ''
Free-form settings mapped to the `qBittorrent.conf` file in the profile.
Refer to <https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent>
you will probably want to run qBittorrent locally once to use the webui to generate the password ByteArray before setting anything here.
'';
example = literalExpression ''
{
LegalNotice.Accepted = true;
BitTorrent.Session = {
port = 43862;
};
Prefences = {
WebUI = {
Port = 8077;
Username = "user";
Passowrd_PBKDR2 = "generated ByteArray.";
General.Locale = "en";
};
}
'';
type = unspecified;
};
};
config = lib.mkIf cfg.enable {
systemd = {
tmpfiles.settings = {
profileDir = {
"${cfg.profileDir}/qBittorrent/"."d" = {
mode = "700";
inherit (cfg) user group;
};
"${cfg.profileDir}/qBittorrent/config/"."d" = {
mode = "700";
inherit (cfg) user group;
};
"${cfg.profileDir}/qBittorrent/config/qBittorrent.conf"."L+" = {
mode = "1400";
inherit (cfg) user group;
argument = "${pkgs.writeText "qBittorrent.conf" (gendeepINI cfg.serverConfig)}";
};
};
};
services.qbittorrent = {
description = "qbittorrent BitTorrent client";
wants = [ "network-online.target" ];
after = [
"local-fs.target"
"network-online.target"
"nss-lookup.target"
];
wantedBy = [ "multi-user.target" ];

serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
UMask = "0066";
ExecStart = "${getExe cfg.package} --profile=${cfg.profileDir}";
TimeoutStopSec = 1800;

PrivateTmp = true;
PrivateNetwork = false;
RemoveIPC = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectHome = "yes";
ProtectProc = "invisible";
ProcSubset = "pid";
ProtectSystem = "strict";
ReadWritePaths = [
"${cfg.profileDir}"
"${cfg.serverConfig.BitTorrent.Session.DefaultSavePath or "${cfg.profileDir}/downloads"}"
"${cfg.serverConfig.BitTorrent.Session.TempPath or "${cfg.profileDir}/downloads/temp"}"
"${cfg.serverConfig.BitTorrent.Session.TorrentExportDirectory or ""}"
];
ProtectClock = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
SystemCallArchitectures = "native";
CapabilityBoundingSet = [
"CAP_NET_ADMIN"
"CAP_SYS_RAWIO"
"CAP_SYS_PTRACE"
"CAP_SYS_NICE"
"CAP_SYS_RESOURCE"
"CAP_NET_BIND_SERVICE"
"CAP_NET_BROADCAST"
"CAP_NET_RAW"
"CAP_AUDIT_*"
"CAP_SYS_ADMIN"
"CAP_SYSLOG"
"CAP_NET_ADMIN"
"CAP_SYS_TIME"
"CAP_SYS_PACCT"
"CAP_KILL"
"CAP_WAKE_ALARM"
"CAP_DAC_OVERRIDE"
"CAP_DAC_READ_SEARCH"
"CAP_FOWNER"
"CAP_IPC_OWNER"
"CAP_LINUX_IMMUTABLE"
"CAP_IPC_LOCK"
"CAP_SYS_MODULE"
"CAP_SYS_TTY_CONFIG"
"CAP_SYS_BOOT"
"CAP_SYS_CHROOT"
"CAP_BLOCK_SYSPEND"
"CAP_LEASE"
"CAP_MKNOD"
"CAP_CHOWN"
"CAP_FSETID"
"CAP_SETFCAP"
"CAP_SETUID"
"CAP_SETGID"
"CAP_SETPCAP"
"CAP_MAC_*"
];
SystemCallFilter = [
"~@aio"
"~@chown"
"~@clock"
"~@cpu-emulation"
"~@cpu-emulation"
"~@debug"
"~@keyring"
"~@memlock"
"~@module"
"~@obsolete"
"~@pkey"
"~@privileged"
"~@setuid"
"~@swap"
"~@resources"
"~@mount"
];
};
};
};

users = {
users = mkIf (cfg.user == "qbittorrent") {
qbittorrent = {
inherit (cfg) group;
isSystemUser = true;
};
};
groups = mkIf (cfg.group == "qbittorrent") { qbittorrent = { }; };
};
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [
cfg.serverConfig.BitTorrent.Preferences.WebUI.Port or 8077
cfg.serverConfig.BitTorrent.Session.Port or 43864
];
};
meta.maintainers = with maintainers; [ nu-nu-ko ];
}

0 comments on commit 35bc83d

Please sign in to comment.