declare qbittorrent
This commit is contained in:
17
flake.lock
generated
17
flake.lock
generated
@@ -1178,6 +1178,7 @@
|
|||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
"stylix": "stylix",
|
"stylix": "stylix",
|
||||||
"synctube": "synctube",
|
"synctube": "synctube",
|
||||||
|
"trackerslist": "trackerslist",
|
||||||
"ucodenix": "ucodenix",
|
"ucodenix": "ucodenix",
|
||||||
"wallpapers": "wallpapers"
|
"wallpapers": "wallpapers"
|
||||||
}
|
}
|
||||||
@@ -1426,6 +1427,22 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"trackerslist": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1775081381,
|
||||||
|
"narHash": "sha256-LXlP3qKShp/8YVA0/lSUJkIbFsInnYtg8jAT5IfjfJk=",
|
||||||
|
"owner": "ngosang",
|
||||||
|
"repo": "trackerslist",
|
||||||
|
"rev": "446d148b04c96e8ffcb4f45f563713764a843ad0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ngosang",
|
||||||
|
"repo": "trackerslist",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ucodenix": {
|
"ucodenix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"cpu-microcodes": "cpu-microcodes"
|
"cpu-microcodes": "cpu-microcodes"
|
||||||
|
|||||||
@@ -76,6 +76,10 @@
|
|||||||
url = "github:StuffAnThings/qbit_manage";
|
url = "github:StuffAnThings/qbit_manage";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
trackerslist = {
|
||||||
|
url = "github:ngosang/trackerslist";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
gallery-dl-src = {
|
gallery-dl-src = {
|
||||||
url = "github:mikf/gallery-dl";
|
url = "github:mikf/gallery-dl";
|
||||||
flake = false;
|
flake = false;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ let
|
|||||||
lidarrMbGapId = 968;
|
lidarrMbGapId = 968;
|
||||||
qbittorrentRouteTable = 200;
|
qbittorrentRouteTable = 200;
|
||||||
serverInterface = config.my.interfaces.server;
|
serverInterface = config.my.interfaces.server;
|
||||||
jawzUid = config.users.users.jawz.uid;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -100,71 +99,85 @@ in
|
|||||||
interfaces.wg0.allowedTCPPorts = [ config.my.servers.nextcloud.port ];
|
interfaces.wg0.allowedTCPPorts = [ config.my.servers.nextcloud.port ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.services.qbittorrent-vpn-routing = lib.mkIf config.my.secureHost {
|
systemd.services.qbittorrent-vpn-routing =
|
||||||
description = "Route qBittorrent user traffic through the VPS WireGuard tunnel";
|
lib.mkIf (config.my.secureHost && config.services.qbittorrent.enable)
|
||||||
wantedBy = [ "multi-user.target" ];
|
{
|
||||||
after = [ "network-online.target" ];
|
description = "Route qBittorrent user traffic through the VPS WireGuard tunnel";
|
||||||
wants = [ "network-online.target" ];
|
before = [ "qbittorrent.service" ];
|
||||||
path = with pkgs; [
|
wantedBy = [ "multi-user.target" ];
|
||||||
coreutils
|
after = [
|
||||||
gnugrep
|
"network-online.target"
|
||||||
iproute2
|
"wireguard-wg0.service"
|
||||||
];
|
];
|
||||||
script = ''
|
wants = [
|
||||||
for _ in $(seq 1 30); do
|
"network-online.target"
|
||||||
if ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
"wireguard-wg0.service"
|
||||||
break
|
];
|
||||||
fi
|
path = with pkgs; [
|
||||||
sleep 1
|
coreutils
|
||||||
done
|
gnugrep
|
||||||
|
iproute2
|
||||||
|
shadow
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
qbit_uid="$(id -u ${config.services.qbittorrent.user})"
|
||||||
|
|
||||||
if ! ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
for _ in $(seq 1 30); do
|
||||||
echo "wg0 is not available"
|
if ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
||||||
exit 1
|
break
|
||||||
fi
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
ip -4 route replace ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
if ! ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
||||||
ip -4 route replace ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
echo "wg0 is not available"
|
||||||
ip -4 route replace ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
ip -4 route replace ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
ip -4 route replace ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
ip -4 route replace ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} 10.88.0.0/16 dev podman0 src 10.88.0.1
|
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} 192.168.100.0/24 dev ${serverInterface} src ${config.my.ips.server}
|
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.ips.vps}/32 via ${config.my.ips.router} dev ${serverInterface} src ${config.my.ips.server}
|
|
||||||
ip -4 route replace table ${toString qbittorrentRouteTable} default via ${config.my.ips.wg-vps} dev wg0 src ${config.my.ips.wg-server}
|
|
||||||
|
|
||||||
while ip -4 rule show | grep -q 'uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}'; do
|
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
||||||
ip -4 rule del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}
|
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
||||||
done
|
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
||||||
|
ip -4 route replace table ${toString qbittorrentRouteTable} 10.88.0.0/16 dev podman0 src 10.88.0.1
|
||||||
|
ip -4 route replace table ${toString qbittorrentRouteTable} 192.168.100.0/24 dev ${serverInterface} src ${config.my.ips.server}
|
||||||
|
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.ips.vps}/32 via ${config.my.ips.router} dev ${serverInterface} src ${config.my.ips.server}
|
||||||
|
ip -4 route replace table ${toString qbittorrentRouteTable} default via ${config.my.ips.wg-vps} dev wg0 src ${config.my.ips.wg-server}
|
||||||
|
|
||||||
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
|
||||||
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable}
|
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable}
|
||||||
done
|
done
|
||||||
|
|
||||||
ip -4 rule add from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} priority 9999
|
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
||||||
ip -4 rule add uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} priority 10000
|
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable}
|
||||||
'';
|
done
|
||||||
preStop = ''
|
|
||||||
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
|
||||||
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} || true
|
|
||||||
done
|
|
||||||
|
|
||||||
while ip -4 rule show | grep -q 'uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}'; do
|
ip -4 rule add from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} priority 9999
|
||||||
ip -4 rule del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} || true
|
ip -4 rule add uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} priority 10000
|
||||||
done
|
'';
|
||||||
|
preStop = ''
|
||||||
|
qbit_uid="$(id -u ${config.services.qbittorrent.user})"
|
||||||
|
|
||||||
ip -4 route del ${config.my.subnets.wg-homelab} dev wg0 || true
|
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
||||||
ip -4 route del ${config.my.subnets.wg-friends} dev wg0 || true
|
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} || true
|
||||||
ip -4 route del ${config.my.subnets.wg-guests} dev wg0 || true
|
done
|
||||||
ip -4 route flush table ${toString qbittorrentRouteTable} || true
|
|
||||||
'';
|
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
|
||||||
serviceConfig = {
|
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} || true
|
||||||
RemainAfterExit = true;
|
done
|
||||||
Type = "oneshot";
|
|
||||||
};
|
ip -4 route del ${config.my.subnets.wg-homelab} dev wg0 || true
|
||||||
};
|
ip -4 route del ${config.my.subnets.wg-friends} dev wg0 || true
|
||||||
|
ip -4 route del ${config.my.subnets.wg-guests} dev wg0 || true
|
||||||
|
ip -4 route flush table ${toString qbittorrentRouteTable} || true
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
RemainAfterExit = true;
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
};
|
||||||
users.users.jawz.packages = builtins.attrValues {
|
users.users.jawz.packages = builtins.attrValues {
|
||||||
inherit (pkgs) podman-compose attic-client;
|
inherit (pkgs) podman-compose attic-client;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -147,7 +147,7 @@
|
|||||||
};
|
};
|
||||||
qbittorrent =
|
qbittorrent =
|
||||||
let
|
let
|
||||||
url = "https://${config.my.ips.server}:${toString config.my.servers.qbittorrent.port}";
|
url = "http://${config.my.ips.server}:${toString config.my.servers.qbittorrent.port}";
|
||||||
name = "qbittorrent";
|
name = "qbittorrent";
|
||||||
in
|
in
|
||||||
lib.mkIf config.my.servers.qbittorrent.enable {
|
lib.mkIf config.my.servers.qbittorrent.enable {
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (inputs) qbit_manage;
|
inherit (inputs) qbit_manage trackerslist;
|
||||||
vuetorrent = pkgs.fetchzip {
|
qbitProfileDir = "/var/lib/qbittorrent";
|
||||||
url = "https://github.com/VueTorrent/VueTorrent/releases/download/v2.31.0/vuetorrent.zip";
|
qbitUser = "qbittorrent";
|
||||||
sha256 = "sha256-kVDnDoCoJlY2Ew71lEMeE67kNOrKTJEMqNj2OfP01qw=";
|
wgInterface = "wg0";
|
||||||
stripRoot = true;
|
qbitDownloadDir = "/srv/pool/multimedia/downloads/torrent";
|
||||||
};
|
qbitIncompleteDir = "${qbitDownloadDir}/.incomplete";
|
||||||
|
additionalTrackers = lib.strings.trim (builtins.readFile "${trackerslist}/trackers_all.txt");
|
||||||
qbit_manageEnv = pkgs.python3.withPackages (
|
qbit_manageEnv = pkgs.python3.withPackages (
|
||||||
ps:
|
ps:
|
||||||
builtins.attrValues {
|
builtins.attrValues {
|
||||||
@@ -33,8 +34,7 @@ let
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
torrentCompletionScript = pkgs.writeShellScript "qbit-torrent-completion" ''
|
torrentCompletionScript = pkgs.writeShellScript "qbit-torrent-completion" ''
|
||||||
chown jawz:piracy -R "$1"
|
chmod -R u+rwX,g+rwX,o-rwx "$1"
|
||||||
chmod -R 775 "$1"
|
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -51,51 +51,75 @@ in
|
|||||||
};
|
};
|
||||||
config = lib.mkIf (config.my.servers.qbittorrent.enable && config.my.secureHost) {
|
config = lib.mkIf (config.my.servers.qbittorrent.enable && config.my.secureHost) {
|
||||||
my.network.firewall.additionalPorts = [ config.my.servers.qbittorrent.port ];
|
my.network.firewall.additionalPorts = [ config.my.servers.qbittorrent.port ];
|
||||||
home-manager.users.jawz.xdg.dataFile.vuetorrent.source = vuetorrent;
|
services.qbittorrent = {
|
||||||
home-manager.users.jawz.imports = [
|
enable = true;
|
||||||
(
|
user = qbitUser;
|
||||||
{ lib, ... }:
|
group = "piracy";
|
||||||
{
|
profileDir = qbitProfileDir;
|
||||||
home.activation.qbittorrentAutorunCommand = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
webuiPort = config.my.servers.qbittorrent.port;
|
||||||
conf=/home/jawz/.config/qBittorrent/qBittorrent.conf
|
torrentingPort = config.my.ports.qbittorrent;
|
||||||
if [ -f "$conf" ]; then
|
extraArgs = [ "--confirm-legal-notice" ];
|
||||||
sed -i \
|
serverConfig = {
|
||||||
's|^program=.*$|program=${torrentCompletionScript} %F|' \
|
AutoRun = {
|
||||||
"$conf"
|
enabled = true;
|
||||||
fi
|
program = "${torrentCompletionScript} %F";
|
||||||
'';
|
};
|
||||||
}
|
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;
|
||||||
|
};
|
||||||
|
Core.AutoDeleteAddedTorrentFile = "Never";
|
||||||
|
Network.PortForwardingEnabled = false;
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
users.users.${qbitUser} = {
|
||||||
|
home = qbitProfileDir;
|
||||||
|
createHome = true;
|
||||||
|
};
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${qbitDownloadDir} 0775 ${qbitUser} piracy -"
|
||||||
|
"d ${qbitIncompleteDir} 0775 ${qbitUser} piracy -"
|
||||||
];
|
];
|
||||||
sops.secrets =
|
sops.secrets =
|
||||||
let
|
let
|
||||||
mkQbitSecret = file: mode: {
|
|
||||||
inherit mode;
|
|
||||||
inherit (config.users.users.jawz) group;
|
|
||||||
sopsFile = ../../secrets/keys.yaml;
|
|
||||||
owner = config.users.users.jawz.name;
|
|
||||||
path = "/home/jawz/.config/qBittorrent/ssl/${file}";
|
|
||||||
};
|
|
||||||
mkUnpackerrSecret = {
|
mkUnpackerrSecret = {
|
||||||
sopsFile = ../../secrets/secrets.yaml;
|
sopsFile = ../../secrets/secrets.yaml;
|
||||||
owner = config.users.users.jawz.name;
|
owner = config.users.users.jawz.name;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"certificates/qbit_cert" = mkQbitSecret "server.crt" "0644";
|
|
||||||
"certificates/qbit_key" = mkQbitSecret "server.key" "0600";
|
|
||||||
"unpackerr/sonarr-api" = mkUnpackerrSecret;
|
"unpackerr/sonarr-api" = mkUnpackerrSecret;
|
||||||
"unpackerr/radarr-api" = mkUnpackerrSecret;
|
"unpackerr/radarr-api" = mkUnpackerrSecret;
|
||||||
};
|
};
|
||||||
systemd = {
|
systemd = {
|
||||||
packages = [
|
packages = [ torrentCompletionScript ];
|
||||||
pkgs.qbittorrent-nox
|
services = {
|
||||||
torrentCompletionScript
|
|
||||||
];
|
|
||||||
services."qbittorrent-nox@jawz" = {
|
|
||||||
enable = true;
|
|
||||||
overrideStrategy = "asDropin";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
};
|
||||||
user = {
|
user = {
|
||||||
services = {
|
services = {
|
||||||
|
|||||||
Reference in New Issue
Block a user