diff --git a/flake.lock b/flake.lock index 3bfef02..34abbaa 100644 --- a/flake.lock +++ b/flake.lock @@ -58,11 +58,11 @@ "quickshell": "quickshell" }, "locked": { - "lastModified": 1765865292, - "narHash": "sha256-BmL32FIn6YtjFG/5Z+BcApTc5Z8mKNLv9wnAU0aRYIE=", + "lastModified": 1765916864, + "narHash": "sha256-mXKYRVK5YndrvgbIKCyz4BRuLkyEqgceF/djXmA6cD8=", "owner": "AvengeMedia", "repo": "DankMaterialShell", - "rev": "2947ff41313566c4eb77fbddf085176141eb337a", + "rev": "672754b0b5efd9e61ea8080c40614ad3b4fd5dbf", "type": "github" }, "original": { @@ -770,11 +770,11 @@ ] }, "locked": { - "lastModified": 1765874996, - "narHash": "sha256-qQjl+fX5ySQzzx+Cc8oua3CSsZA5lK6Ev6XEmjxKbHs=", + "lastModified": 1765918270, + "narHash": "sha256-TbNcuaNCIRp4ZcZBQ1lyXW6GMyHhY5+gWCHqKTLZ3So=", "owner": "nix-community", "repo": "NUR", - "rev": "1d585f45ed47164867626b03b7f192f2cddaa606", + "rev": "e62aaff51af4cbc43149a71b67931005416d1138", "type": "github" }, "original": { diff --git a/hosts/desktop/monitors.nix b/hosts/desktop/monitors.nix index 384f647..b18b2af 100644 --- a/hosts/desktop/monitors.nix +++ b/hosts/desktop/monitors.nix @@ -1,7 +1,7 @@ _: { monitors = [ { - name = "DP-1"; + name = "DP-3"; resolution = { width = 2560; height = 1440; @@ -14,7 +14,7 @@ _: { }; } { - name = "DP-3"; + name = "DP-2"; resolution = { width = 2560; height = 1440; diff --git a/modules/homelab/glance.nix b/modules/homelab/glance.nix index 478a639..cef8282 100644 --- a/modules/homelab/glance.nix +++ b/modules/homelab/glance.nix @@ -12,8 +12,8 @@ lib.mkIf config.fireproof.homelab.enable (let src = pkgs.fetchFromGitHub { owner = "nickolaj-jepsen"; repo = "glance"; - rev = "7ea37f329e17908cdcc306f0fbb23a62e7c50584"; - hash = "sha256-ZU9iswhgQPeMZeQmzgNhFBcO2TzWYrmIWPnKSAA0fFM="; + rev = "c490067f87186cac9084a76010a646119b7793e1"; + hash = "sha256-zsanWSWO/gY4ZuYssdcoGKVw/Yk29qaF5Gn5XUYKQhk="; }; }); diff --git a/modules/homelab/qbittorrent.nix b/modules/homelab/qbittorrent.nix index d6dc1e4..7c0b211 100644 --- a/modules/homelab/qbittorrent.nix +++ b/modules/homelab/qbittorrent.nix @@ -5,31 +5,13 @@ ... }: lib.mkIf config.fireproof.homelab.enable (let - inherit (config.fireproof) username; - user = "media"; - group = "media"; - # VPN namespace configuration - vpnNamespace = "vpn"; - vpnInterface = "wg0"; + vpnNamespace = "qbittorrent-vpn"; + vpnInterface = "qbt-wg0"; # Ports webUiPort = 8082; torrentPort = 51413; - - mkVirtualHost = port: { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://localhost:${toString port}"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; in { # Secrets for Mullvad WireGuard config # mullvad-wg.age should contain just the WireGuard config (not the Address line): @@ -66,30 +48,11 @@ in { # Create network namespace if it doesn't exist ip netns add ${vpnNamespace} || true - # Create veth pair for communication between namespaces - ip link add veth-vpn type veth peer name veth-vpn-br || true - ip link set veth-vpn-br netns ${vpnNamespace} || true - - # Configure host side - ip addr add 10.200.200.1/24 dev veth-vpn || true - ip link set veth-vpn up - - # Configure namespace side - ip netns exec ${vpnNamespace} ip addr add 10.200.200.2/24 dev veth-vpn-br || true - ip netns exec ${vpnNamespace} ip link set veth-vpn-br up + # Set up loopback interface in namespace ip netns exec ${vpnNamespace} ip link set lo up - - # Enable IP forwarding for the veth bridge - echo 1 > /proc/sys/net/ipv4/ip_forward - iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o veth-vpn -j MASQUERADE || true - - # Allow traffic from namespace to host for web UI - iptables -A FORWARD -i veth-vpn -o veth-vpn -j ACCEPT || true ''; ExecStop = pkgs.writeShellScript "destroy-vpn-netns" '' - ip link del veth-vpn || true ip netns del ${vpnNamespace} || true - iptables -t nat -D POSTROUTING -s 10.200.200.0/24 -o veth-vpn -j MASQUERADE || true ''; }; }; @@ -107,8 +70,12 @@ in { RemainAfterExit = true; ExecStart = pkgs.writeShellScript "setup-wg-vpn" '' set -ex - # Create WireGuard interface in namespace - ip link add ${vpnInterface} type wireguard || true + # Clean up any existing WireGuard interface first + ip link del ${vpnInterface} 2>/dev/null || true + ip netns exec ${vpnNamespace} ip link del ${vpnInterface} 2>/dev/null || true + + # Create WireGuard interface + ip link add ${vpnInterface} type wireguard ip link set ${vpnInterface} netns ${vpnNamespace} # Configure WireGuard with Mullvad config @@ -116,7 +83,7 @@ in { # Set the interface address from secret file WG_ADDR=$(cat ${config.age.secrets.mullvad-wg-address.path}) - ip netns exec ${vpnNamespace} ip addr add "$WG_ADDR" dev ${vpnInterface} || true + ip netns exec ${vpnNamespace} ip addr add "$WG_ADDR" dev ${vpnInterface} ip netns exec ${vpnNamespace} ip link set ${vpnInterface} up # Route all traffic through WireGuard (default route) @@ -134,25 +101,43 @@ in { }; # qBittorrent service running inside the VPN namespace + services.qbittorrent = { + enable = true; + user = "media"; + group = "media"; + webuiPort = webUiPort; + torrentingPort = torrentPort; + serverConfig = { + LegalNotice.Accepted = true; + Preferences = { + WebUI = { + Address = "*"; + Port = webUiPort; + }; + Connection = { + PortRangeMin = torrentPort; + }; + Downloads = { + SavePath = "/mnt/data/torrent"; + }; + }; + }; + }; + + # Override the qbittorrent service to run in VPN namespace systemd.services.qbittorrent = { - description = "qBittorrent-nox service"; - documentation = ["man:qbittorrent-nox(1)"]; after = [ "network.target" "wg-${vpnNamespace}.service" ]; requires = ["wg-${vpnNamespace}.service"]; - wantedBy = ["multi-user.target"]; serviceConfig = { - Type = "simple"; - User = user; - Group = group; - StateDirectory = "qbittorrent"; # Run in the VPN namespace NetworkNamespacePath = "/var/run/netns/${vpnNamespace}"; - ExecStart = "${pkgs.qbittorrent-nox}/bin/qbittorrent-nox --webui-port=${toString webUiPort}"; - Restart = "on-failure"; - TimeoutStopSec = 1800; + # Bind mount the DNS config into the namespace + BindReadOnlyPaths = [ + "/etc/netns/${vpnNamespace}/resolv.conf:/etc/resolv.conf" + ]; }; }; @@ -162,14 +147,15 @@ in { after = ["qbittorrent.service"]; requires = ["qbittorrent.service"]; wantedBy = ["multi-user.target"]; + path = with pkgs; [iproute2 socat]; serviceConfig = { Type = "simple"; Restart = "on-failure"; - ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:${toString webUiPort},fork,reuseaddr EXEC:'${pkgs.iproute2}/bin/ip netns exec ${vpnNamespace} ${pkgs.socat}/bin/socat STDIO TCP\\:127.0.0.1\\:${toString webUiPort}'"; + ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:${toString webUiPort},fork,reuseaddr,bind=0.0.0.0 EXEC:'${pkgs.iproute2}/bin/ip netns exec ${vpnNamespace} ${pkgs.socat}/bin/socat STDIO TCP\\:127.0.0.1\\:${toString webUiPort}'"; }; }; - # Firewall rules for torrent port (forwarded through VPN) + # Firewall rules networking.firewall.allowedTCPPorts = [webUiPort]; networking.firewall.allowedUDPPorts = [torrentPort]; @@ -178,7 +164,19 @@ in { "qbittorrent.nickolaj.com".allowed_groups = ["arr"]; }; nginx.virtualHosts = { - "qbittorrent.nickolaj.com" = mkVirtualHost webUiPort; + "qbittorrent.nickolaj.com" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:${toString webUiPort}"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; }; restic.backups.homelab.paths = [ diff --git a/secrets/hosts/homelab/.rekey/d859968712603cab333f122fce8c5714-mullvad-wg-address.age b/secrets/hosts/homelab/.rekey/d859968712603cab333f122fce8c5714-mullvad-wg-address.age new file mode 100644 index 0000000..bdde4bb --- /dev/null +++ b/secrets/hosts/homelab/.rekey/d859968712603cab333f122fce8c5714-mullvad-wg-address.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 uxq+Zw 5GTpmg1JYdchll7KGFza4+Wr2HUrspkUy263EjosImI +FI/rKWr8SRFjX46ABgBAtOfF+tm5Si1T6uWC5K0EXmQ +-> 1\y>D-grease b s$Uo} +rw0Ut3iYFuMxeoj+6/VBi5qrKioY/Es +--- 7hpSVWwDE2aWWdKs60R94/87gI3IcqVY9z8PV4SlTpg +ü»0úŒµ ‘”äÍH +Ã,l± $°)^È)Ñ¨Ö ¹£iˆFà¨pŸ™Øåì¾s‰7Á \ No newline at end of file diff --git a/secrets/hosts/homelab/.rekey/d9f3f0acb9b58b9bddaabebd55da6816-mullvad-wg.age b/secrets/hosts/homelab/.rekey/d9f3f0acb9b58b9bddaabebd55da6816-mullvad-wg.age new file mode 100644 index 0000000..43ff121 Binary files /dev/null and b/secrets/hosts/homelab/.rekey/d9f3f0acb9b58b9bddaabebd55da6816-mullvad-wg.age differ diff --git a/secrets/hosts/homelab/mullvad-wg-address.age b/secrets/hosts/homelab/mullvad-wg-address.age new file mode 100644 index 0000000..d90b6f7 Binary files /dev/null and b/secrets/hosts/homelab/mullvad-wg-address.age differ diff --git a/secrets/hosts/homelab/mullvad-wg.age b/secrets/hosts/homelab/mullvad-wg.age new file mode 100644 index 0000000..ce1622a Binary files /dev/null and b/secrets/hosts/homelab/mullvad-wg.age differ