{ lib, config, pkgs, ... }: { options.server.deluge.enable = lib.mkEnableOption "Enable deluge torrent client"; config = lib.mkIf config.server.deluge.enable { services.deluge = { enable = true; web.enable = true; }; environment.systemPackages = with pkgs; [ libnatpmp ]; networking.firewall.allowedTCPPorts = [ 8112 ]; # creating network namespace systemd.services."netns@" = { description = "%I network namespace"; before = [ "network.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStart = "${pkgs.iproute2}/bin/ip netns add %I"; ExecStop = "${pkgs.iproute2}/bin/ip netns del %I"; }; }; systemd.services.wg-port-opener = { description = "port opener for protonvpn"; bindsTo = [ "netns@wg.service" ]; requires = [ "network-online.target" ]; after = [ "netns@wg.service" ]; serviceConfig = { Type = "exec"; NetworkNamespacePath = [ "/var/run/netns/wg" ]; ExecStart = with pkgs; writers.writeBash "port-opening" '' while true; do date; ${libnatpmp}/bin/natpmpc -a 1 0 udp 60 -g 10.2.0.1 || { echo -e "ERROR with natpmpc udp command \a" ; break ; }; ${libnatpmp}/bin/natpmpc -a 1 0 tcp 60 -g 10.2.0.1 || { echo -e "ERROR with natpmpc tcp command \a" ; break ; }; sleep 45; done; ''; }; }; # setting up wireguard interface within network namespace systemd.services.wg = { description = "wg network interface"; bindsTo = [ "netns@wg.service" ]; requires = [ "network-online.target" ]; after = [ "netns@wg.service" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStart = with pkgs; writers.writeBash "wg-up" '' ${iproute2}/bin/ip link add wg0 type wireguard ${iproute2}/bin/ip link set wg0 netns wg ${iproute2}/bin/ip -n wg address add 10.2.0.2/32 dev wg0 # ${iproute2}/bin/ip -n wg -6 address add fc00:bbbb:bbbb:bb01::a:1674/128 dev wg0 ${iproute2}/bin/ip netns exec wg \ ${wireguard-tools}/bin/wg setconf wg0 /root/proton.conf ${iproute2}/bin/ip -n wg link set wg0 up # need to set lo up as network namespace is started with lo down ${iproute2}/bin/ip -n wg link set lo up ${iproute2}/bin/ip -n wg route add default dev wg0 ${iproute2}/bin/ip -n wg -6 route add default dev wg0 ''; ExecStop = with pkgs; writers.writeBash "wg-down" '' ${iproute2}/bin/ip -n wg route del default dev wg0 ${iproute2}/bin/ip -n wg -6 route del default dev wg0 ${iproute2}/bin/ip -n wg link del wg0 ''; }; }; # binding deluged to network namespace systemd.services.deluged.bindsTo = [ "netns@wg.service" ]; systemd.services.deluged.requires = [ "network-online.target" "wg.service" ]; systemd.services.deluged.serviceConfig.NetworkNamespacePath = [ "/var/run/netns/wg" ]; systemd.services.deluge-port-setter = { description = "sets deluge ports"; bindsTo = [ "netns@wg.service" ]; requires = [ "network-online.target" ]; after = [ "deluged.service" ]; serviceConfig = { Type = "oneshot"; User = "deluge"; RemainAfterExit = true; NetworkNamespacePath = [ "/var/run/netns/wg" ]; ExecStart = with pkgs; writers.writeBash "deluge-ports" '' TCP=($(${libnatpmp}/bin/natpmpc -a 1 0 tcp 60 -g 10.2.0.1 2> /dev/null | grep Mapped)) TCP_PORT=''${TCP[3]} UDP=($(${libnatpmp}/bin/natpmpc -a 1 0 udp 60 -g 10.2.0.1 2> /dev/null | grep Mapped)) UDP_PORT=''${UDP[3]} echo "The ports are" echo "TCP: $TCP_PORT" echo "UDP: $UDP_PORT" PORTS="($TCP_PORT, $UDP_PORT)" ${deluge}/bin/deluge-console "config -s random_port false; config -s listen_ports $PORTS" exit 0 ''; }; }; # allowing delugeweb to access deluged in network namespace, a socket is necesarry systemd.sockets."proxy-to-deluged" = { enable = true; description = "Socket for Proxy to Deluge Daemon"; listenStreams = [ "58846" ]; wantedBy = [ "sockets.target" ]; }; # creating proxy service on socket, which forwards the same port from the root namespace to the isolated namespace systemd.services."proxy-to-deluged" = { enable = true; description = "Proxy to Deluge Daemon in Network Namespace"; requires = [ "deluged.service" "proxy-to-deluged.socket" ]; after = [ "deluged.service" "proxy-to-deluged.socket" ]; unitConfig = { JoinsNamespaceOf = "deluged.service"; }; serviceConfig = { User = "deluge"; Group = "deluge"; ExecStart = "${pkgs.systemd}/lib/systemd/systemd-socket-proxyd --exit-idle-time=5min 127.0.0.1:58846"; PrivateNetwork = "yes"; }; }; }; }