{ pkgs, config, lib, inputs, ... }: let lidarrMbGapId = 968; qbittorrentRouteTable = 200; serverInterface = config.my.interfaces.server; jawzUid = config.users.users.jawz.uid; in { imports = [ inputs.lidarr-mb-gap.nixosModules.lidarr-mb-gap ./hardware-configuration.nix ../../config/base.nix ../../config/stylix.nix ]; my = import ./toggles.nix { inherit config inputs; } // { nix.cores = 6; users.nixremote = { enable = true; authorizedKeys = inputs.self.lib.getSshKeys [ "nixworkstation" "nixminiserver" ]; }; network.firewall = { enabledServicePorts = true; additionalPorts = [ 2049 # idk config.my.ports.syncthingGui config.my.ports.syncthingRelay config.my.ports.sonarqube config.my.ports.synapseSsl config.my.ports.tdarr config.my.ports.mediaMap config.my.ports.qbittorrent ]; }; }; nix.buildMachines = [ { hostName = "workstation"; system = "x86_64-linux"; sshUser = "nixremote"; maxJobs = 8; speedFactor = 2; supportedFeatures = config.my.nix.features; } ]; nixpkgs.config.permittedInsecurePackages = [ "mbedtls-2.28.10" ]; sops.secrets = { "server/private" = lib.mkIf config.my.secureHost { sopsFile = ../../secrets/wireguard.yaml; }; lidarr-mb-gap = lib.mkIf config.my.secureHost { sopsFile = ../../secrets/env.yaml; }; "private_keys/lidarr-mb-gap" = let cfg = config.services.lidarr-mb-gap; usr = config.users.users.lidarr-mb-gap; in lib.mkIf (config.my.secureHost && cfg.enable) { sopsFile = ../../secrets/keys.yaml; owner = usr.name; inherit (usr) group; path = "${usr.home}/.ssh/ed25519_lidarr-mb-gap"; }; }; networking = { hostName = "server"; iproute2.rttablesExtraConfig = '' ${toString qbittorrentRouteTable} qbittorrent ''; wireguard.interfaces.wg0 = lib.mkIf config.my.secureHost { allowedIPsAsRoutes = false; ips = [ "${config.my.ips.wg-server}/32" ]; privateKeyFile = config.sops.secrets."server/private".path; peers = [ { publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY="; endpoint = "${config.my.ips.vps}:51820"; allowedIPs = [ "0.0.0.0/0" "${config.my.ips.wg-vps}/32" config.my.subnets.wg-homelab config.my.subnets.wg-friends config.my.subnets.wg-guests ]; persistentKeepalive = 25; } ]; }; firewall = { allowedUDPPorts = config.networking.firewall.allowedTCPPorts; interfaces.wg0.allowedTCPPorts = [ config.my.servers.nextcloud.port ]; }; }; systemd.services.qbittorrent-vpn-routing = lib.mkIf config.my.secureHost { description = "Route qBittorrent user traffic through the VPS WireGuard tunnel"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; path = with pkgs; [ coreutils gnugrep iproute2 ]; script = '' for _ in $(seq 1 30); do if ip -4 addr show dev wg0 >/dev/null 2>&1; then break fi sleep 1 done if ! ip -4 addr show dev wg0 >/dev/null 2>&1; then echo "wg0 is not available" exit 1 fi ip -4 route replace ${config.my.subnets.wg-homelab} 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 ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server} ip -4 route replace table ${toString qbittorrentRouteTable} ${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 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 'uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}'; do ip -4 rule del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} done 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} done ip -4 rule add from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} priority 9999 ip -4 rule add uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} priority 10000 ''; 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 del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} || true done 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 { inherit (pkgs) podman-compose attic-client; }; users.groups.lidarr-mb-gap.gid = lidarrMbGapId; users.users.lidarr-mb-gap = { uid = lidarrMbGapId; isSystemUser = true; group = "lidarr-mb-gap"; home = "/var/lib/lidarr-mb-gap"; }; services = { btrfs.autoScrub = { enable = true; fileSystems = [ "/" "/srv/pool" ]; }; lidarr-mb-gap = { enable = true; package = inputs.lidarr-mb-gap.packages.${pkgs.stdenv.hostPlatform.system}.lidarr-mb-gap; home = "/var/lib/lidarr-mb-gap"; envFile = config.sops.secrets.lidarr-mb-gap.path; runInterval = "weekly"; syncToVPS = true; vpsPort = 3456; vpsHost = "lidarr-reports@${config.my.ips.vps}"; vpsPath = "/var/www/html/lidarr-mb-gap"; sshKeyFile = config.sops.secrets."private_keys/lidarr-mb-gap".path; sshKnownHosts.vps = { hostNames = [ config.my.ips.vps "[${config.my.ips.vps}]:3456" ]; publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPp0wAuZXk96OyA/+2YpQalokS9lZdacjJqY9zN8IScP"; }; }; }; }