Files
NixOS/modules/servers/qbittorrent.nix
Danilo Reyes 4eeed32002
All checks were successful
MCP Tests / mcp-tests (push) Successful in 24s
qbittorrent + qbit_manage migrated to nixpkgs
2026-04-01 23:55:32 -06:00

153 lines
5.3 KiB
Nix

{
inputs,
lib,
config,
pkgs,
...
}:
let
inherit (inputs) trackerslist;
qbitProfileDir = "/var/lib/qbittorrent";
qbitUser = "qbittorrent";
wgInterface = "wg0";
qbitManageConfigPath = "/home/jawz/.config/qbit_manage/config.yml";
qbitDownloadDir = "/srv/pool/multimedia/downloads/torrent";
qbitIncompleteDir = "${qbitDownloadDir}/.incomplete";
additionalTrackers = lib.strings.trim (builtins.readFile "${trackerslist}/trackers_all.txt");
unstablePkgs = import inputs.nixpkgs-unstable {
inherit (pkgs.stdenv.hostPlatform) system;
config.allowUnfree = true;
};
qbitManagePkg = unstablePkgs."qbit-manage";
torrentCompletionScript = pkgs.writeShellScript "qbit-torrent-completion" ''
chmod -R u+rwX,g+rwX,o-rwx "$1"
'';
in
{
options.my.servers = {
unpackerr.enable = lib.mkEnableOption "automatic archive extraction service";
qbittorrent = {
enable = lib.mkEnableOption "qBittorrent torrent client";
port = lib.mkOption {
type = lib.types.int;
default = 9091;
description = "The port to access qbittorrent web-ui";
};
};
};
config = lib.mkIf (config.my.servers.qbittorrent.enable && config.my.secureHost) {
my.network.firewall.additionalPorts = [ config.my.servers.qbittorrent.port ];
services.qbittorrent = {
enable = true;
user = qbitUser;
group = "piracy";
profileDir = qbitProfileDir;
webuiPort = config.my.servers.qbittorrent.port;
torrentingPort = config.my.ports.qbittorrent;
extraArgs = [ "--confirm-legal-notice" ];
serverConfig = {
Core.AutoDeleteAddedTorrentFile = "Never";
Network.PortForwardingEnabled = false;
AutoRun = {
enabled = true;
program = "${torrentCompletionScript} %F";
};
Preferences = {
Bittorrent.CustomizeTrackersListUrl = "https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_all.txt";
WebUI = {
AlternativeUIEnabled = true;
HTTPS.Enabled = false;
Password_PBKDF2 = "@ByteArray(ZYy4l3ORHihzBrRYqIfmOA==:SYv4Gor5ZSI9FfAPOxAAdhlmz/h+vViEHnoW6tfJYLNnFL9DQ8udqkO9Na83RJauzhVVGvAgauPq/y4UNPyl3g==)";
ReverseProxySupportEnabled = false;
RootFolder = "${pkgs.vuetorrent}/share/vuetorrent";
Username = "9VcZWt3d0u6mmMOhryUZAcpIe8WML9J7Icj00Vu5fuOFXRB0ECAItetKAK1NnfrD";
};
};
BitTorrent.Session = {
AddExtensionToIncompleteFiles = true;
AddTrackersEnabled = true;
AdditionalTrackers = additionalTrackers;
AnnounceIP = config.my.ips.vps;
DefaultSavePath = qbitDownloadDir;
GlobalMaxRatio = 1;
GlobalMaxSeedingMinutes = 120;
Interface = wgInterface;
InterfaceAddress = config.my.ips.wg-server;
InterfaceName = wgInterface;
MaxActiveDownloads = 5;
MaxActiveTorrents = 100;
MaxActiveUploads = 90;
QueueingSystemEnabled = true;
ShareLimitAction = "Stop";
TempPath = qbitIncompleteDir;
TempPathEnabled = true;
};
};
};
users.users.${qbitUser} = {
createHome = true;
isSystemUser = true;
home = qbitProfileDir;
};
sops.secrets =
let
mkUnpackerrSecret = {
sopsFile = ../../secrets/secrets.yaml;
owner = config.users.users.jawz.name;
};
in
{
"unpackerr/sonarr-api" = mkUnpackerrSecret;
"unpackerr/radarr-api" = mkUnpackerrSecret;
};
systemd = {
packages = [ torrentCompletionScript ];
tmpfiles.rules = [
"d ${qbitDownloadDir} 0775 ${qbitUser} piracy -"
"d ${qbitIncompleteDir} 0775 ${qbitUser} piracy -"
];
user = {
services = {
unpackerr = lib.mkIf config.my.servers.unpackerr.enable {
enable = true;
restartIfChanged = true;
description = "Run unpackerr";
wantedBy = [ "default.target" ];
environment = {
UN_FILE_MODE = "0664";
UN_DIR_MODE = "0775";
UN_SONARR_0_URL = config.my.servers.sonarr.local;
UN_SONARR_0_API_KEY = "filepath:${config.sops.secrets."unpackerr/sonarr-api".path}";
UN_SONARR_0_PATHS = "/srv/pool/multimedia/downloads/torrent";
UN_RADARR_0_URL = config.my.servers.radarr.local;
UN_RADARR_0_API_KEY = "filepath:${config.sops.secrets."unpackerr/radarr-api".path}";
UN_RADARR_0_PATHS = "/srv/pool/multimedia/downloads/torrent";
};
serviceConfig = {
Restart = "on-failure";
RestartSec = 30;
ExecStart = "${pkgs.unpackerr}/bin/unpackerr";
};
};
qbit_manage = {
restartIfChanged = true;
description = "Tidy up my torrents";
wantedBy = [ "default.target" ];
serviceConfig = {
Type = "oneshot";
TimeoutStartSec = "5min";
ExecStart = "${qbitManagePkg}/bin/qbit-manage -r -c ${qbitManageConfigPath}";
};
};
};
timers.qbit_manage = {
enable = true;
description = "Tidy up my torrents";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "*:0/10";
};
};
};
};
}