From fd08987e124d911758b1f7432bc9655064501468 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sat, 11 Apr 2026 08:21:37 -0500 Subject: [PATCH] media: add natpmpc-helper sidecar for ProtonVPN port forwarding Adds a lightweight Alpine sidecar that runs natpmpc against the ProtonVPN NAT-PMP gateway (10.2.0.1) every 45s to maintain a forwarded port, then updates qBittorrent's listen port via API. Without inbound port forwarding peers can only be dialed out to, which severely limits download speeds on a gigabit connection. --- .../legion/k8s/media/gluetun-qbittorrent.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/servers/legion/k8s/media/gluetun-qbittorrent.yaml b/servers/legion/k8s/media/gluetun-qbittorrent.yaml index 7cdb359..cb9c58f 100644 --- a/servers/legion/k8s/media/gluetun-qbittorrent.yaml +++ b/servers/legion/k8s/media/gluetun-qbittorrent.yaml @@ -66,6 +66,44 @@ spec: memory: 512Mi cpu: 200m + # NAT-PMP helper — requests a forwarded port from ProtonVPN gateway every 45s + # and updates qBittorrent's listen port so peers can connect inbound + - name: natpmpc-helper + image: alpine:latest + command: + - sh + - -c + - | + apk add -q natpmpc curl 2>/dev/null + echo "Waiting for VPN and qBittorrent to start..." + sleep 30 + while true; do + # Request port forwarding from ProtonVPN NAT-PMP gateway + OUT=$(natpmpc -a 0 0 udp 60 -g 10.2.0.1 2>&1) + PORT=$(echo "$OUT" | grep -oE 'Mapped public port [0-9]+' | grep -oE '[0-9]+$') + if [ -n "$PORT" ]; then + echo "$(date): Got forwarded port $PORT" + # Also request TCP mapping for the same port + natpmpc -a "$PORT" "$PORT" tcp 60 -g 10.2.0.1 >/dev/null 2>&1 + # Update qBittorrent listen port + SID=$(curl -s -c /tmp/qbt.txt -X POST http://localhost:8080/api/v2/auth/login \ + -d "username=admin&password=adminadmin" 2>/dev/null) + curl -s -b /tmp/qbt.txt -X POST http://localhost:8080/api/v2/app/setPreferences \ + -d "{\"json\":{\"listen_port\":$PORT,\"random_port\":false}}" >/dev/null 2>&1 + echo "$(date): qBittorrent listen port set to $PORT" + else + echo "$(date): NAT-PMP failed: $OUT" + fi + sleep 45 + done + resources: + requests: + memory: 16Mi + cpu: 10m + limits: + memory: 32Mi + cpu: 50m + # qBittorrent — shares gluetun's network namespace, all traffic through VPN - name: qbittorrent image: lscr.io/linuxserver/qbittorrent:latest