2022-03-18 22:14:09 +01:00
|
|
|
{ config, inputs, lib, pkgs, ... }:
|
|
|
|
let
|
|
|
|
cfg = config.sbruder.qbittorrent;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options.sbruder.qbittorrent = {
|
|
|
|
enable = lib.mkEnableOption "the qbittorrent service";
|
|
|
|
homeDir = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
default = "/var/lib/qbittorrent";
|
|
|
|
};
|
|
|
|
configDir = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
default = "${cfg.homeDir}/config";
|
|
|
|
};
|
|
|
|
downloadDir = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
default = "${cfg.homeDir}/download";
|
|
|
|
};
|
|
|
|
webuiPort = lib.mkOption {
|
|
|
|
type = lib.types.int;
|
|
|
|
default = 8099;
|
|
|
|
};
|
|
|
|
sopsFile = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
default = ../../machines/${config.networking.hostName}/secrets.yaml;
|
|
|
|
description = ''
|
|
|
|
The sops secret file that includes the wireguard private key (wg-qbittorrent-private-key).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
wireguardConnectionDetails = lib.mkOption {
|
|
|
|
type = lib.types.attrs;
|
|
|
|
default = import ../../machines/${config.networking.hostName}/secrets/wireguard-qbittorrent.nix;
|
|
|
|
example = {
|
|
|
|
ips = [ "10.0.0.1/32" "fd00::1/128" ];
|
|
|
|
|
|
|
|
peers = lib.singleton {
|
|
|
|
publicKey = "MbLFO7MIFSdwVmZWQG//IUxVxwSHprRkhr/NWl2gils=";
|
|
|
|
allowedIPs = [ "0.0.0.0/0" "::0/0" ];
|
|
|
|
endpoint = "192.0.2.1:51820";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
description = "The connection details for the WireGuard tunnel.";
|
|
|
|
};
|
|
|
|
fqdn = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "The fqdn nginx should listen on. It must not be used for anything else.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = lib.mkIf cfg.enable
|
|
|
|
{
|
|
|
|
users.users.qbittorrent = {
|
|
|
|
group = "qbittorrent";
|
|
|
|
home = cfg.homeDir;
|
|
|
|
isSystemUser = true;
|
|
|
|
};
|
|
|
|
users.groups.qbittorrent = { };
|
|
|
|
|
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
"d '${cfg.downloadDir}' 0775 qbittorrent users - -"
|
|
|
|
"d '${cfg.homeDir}' 0771 qbittorrent qbittorrent - -"
|
|
|
|
];
|
|
|
|
|
|
|
|
sops.secrets.wg-qbittorrent-private-key.sopsFile = cfg.sopsFile;
|
|
|
|
|
|
|
|
networking.wireguard.interfaces.wg-qbittorrent = {
|
|
|
|
interfaceNamespace = "qbittorrent";
|
|
|
|
preSetup = "ip netns add qbittorrent && ip -n qbittorrent link set lo up";
|
|
|
|
postShutdown = "ip netns del qbittorrent";
|
|
|
|
|
|
|
|
privateKeyFile = config.sops.secrets.wg-qbittorrent-private-key.path;
|
|
|
|
} // (builtins.removeAttrs cfg.wireguardConnectionDetails [ "nameserver" ]);
|
|
|
|
|
|
|
|
environment.etc."netns/qbittorrent/resolv.conf".text = ''
|
|
|
|
nameserver ${cfg.wireguardConnectionDetails.nameserver}
|
|
|
|
'';
|
|
|
|
|
|
|
|
systemd.services.qbittorrent = {
|
|
|
|
description = "qBittorrent Service";
|
|
|
|
after = [ "wireguard-wg-qbittorrent.service" ];
|
|
|
|
requires = [ "wireguard-wg-qbittorrent.service" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
|
|
|
|
serviceConfig = {
|
|
|
|
PrivateNetwork = true;
|
|
|
|
NetworkNamespacePath = "/run/netns/qbittorrent";
|
|
|
|
|
|
|
|
Restart = "always";
|
|
|
|
ExecStart = "${pkgs.qbittorrent-nox}/bin/qbittorrent-nox --profile=${cfg.configDir} --webui-port=${toString cfg.webuiPort}";
|
|
|
|
User = "qbittorrent";
|
|
|
|
Group = "qbittorrent";
|
|
|
|
|
|
|
|
# Increase number of open file descriptors (default: 1024)
|
|
|
|
LimitNOFILE = 65536;
|
|
|
|
|
2023-10-04 17:01:35 +02:00
|
|
|
# Avoid using nscd (leaks dns)
|
|
|
|
InaccessiblePaths = [
|
|
|
|
"/run/nscd"
|
|
|
|
];
|
|
|
|
# Make correct resolv.conf available for unit
|
|
|
|
BindReadOnlyPaths = [
|
|
|
|
"/etc/netns/qbittorrent/resolv.conf:/etc/resolv.conf"
|
|
|
|
];
|
|
|
|
|
|
|
|
|
2022-03-18 22:14:09 +01:00
|
|
|
# systemd-analyze --no-pager security qbittorrent.service
|
|
|
|
CapabilityBoundingSet = null;
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
PrivateUsers = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
SystemCallFilter = "@system-service";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.qbittorrent-webui-proxy = {
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
after = [ "wireguard-wg-qbittorrent.service" ];
|
|
|
|
partOf = [ "wireguard-wg-qbittorrent.service" ];
|
|
|
|
|
|
|
|
serviceConfig = {
|
|
|
|
PrivateNetwork = true;
|
|
|
|
NetworkNamespacePath = "/run/netns/qbittorrent";
|
|
|
|
|
|
|
|
Restart = "always";
|
|
|
|
ExecStart = "${pkgs.socat}/bin/socat UNIX-LISTEN:${cfg.homeDir}/webui.sock,fork,reuseaddr,mode=660,unlink-early TCP:127.0.0.1:${toString cfg.webuiPort}";
|
|
|
|
User = "qbittorrent";
|
|
|
|
Group = "nginx";
|
|
|
|
|
|
|
|
# systemd-analyze --no-pager security qbittorrent-webui-proxy.service
|
|
|
|
CapabilityBoundingSet = null;
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
PrivateUsers = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
SystemCallFilter = "@system-service";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.qbittorrent_exporter = {
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
after = [ "network.target" ];
|
|
|
|
environment = {
|
|
|
|
QBITTORRENT_API_SOCKET = "${cfg.homeDir}/webui.sock";
|
|
|
|
QBITTORRENT_EXPORTER_LISTEN_ADDRESS = ":9561";
|
|
|
|
};
|
|
|
|
serviceConfig = {
|
|
|
|
ExecStart = "${pkgs.callPackage ./exporter { }}/bin/qbittorrent_exporter";
|
|
|
|
Restart = "always";
|
|
|
|
User = "qbittorrent";
|
|
|
|
Group = "qbittorrent";
|
|
|
|
|
|
|
|
# systemd-analyze --no-pager security qbittorrent_exporter.service
|
|
|
|
CapabilityBoundingSet = null;
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateUsers = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
SystemCallFilter = "@system-service";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
services.nginx.virtualHosts."${cfg.fqdn}" = {
|
2022-10-07 22:19:58 +02:00
|
|
|
enableACME = lib.mkDefault true;
|
|
|
|
forceSSL = lib.mkDefault true;
|
2022-03-18 22:14:09 +01:00
|
|
|
|
|
|
|
# treated as state
|
|
|
|
basicAuthFile = "${cfg.homeDir}/htpasswd";
|
|
|
|
|
|
|
|
locations = {
|
|
|
|
"/" = {
|
|
|
|
proxyPass = "http://unix:${cfg.homeDir}/webui.sock";
|
|
|
|
proxyWebsockets = true;
|
|
|
|
};
|
|
|
|
"/download/" = {
|
|
|
|
alias = "${cfg.downloadDir}/";
|
|
|
|
extraConfig = ''
|
|
|
|
autoindex on;
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
"=/metrics" = {
|
|
|
|
proxyPass = "http://127.0.0.1:9561/metrics";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|