Skip to content

feat(extras/scripts): update qBittorrent peer port with optional authentication#2700

Open
astappiev wants to merge 14 commits intoqdm12:masterfrom
astappiev:qbittorrent
Open

feat(extras/scripts): update qBittorrent peer port with optional authentication#2700
astappiev wants to merge 14 commits intoqdm12:masterfrom
astappiev:qbittorrent

Conversation

@astappiev
Copy link
Copy Markdown

@astappiev astappiev commented Feb 13, 2025

Inspired by #2611 and talks in #1555 created a script to update peer-port of qBittorrent.

Upd: added option to authenticate.

@AndaPlays
Copy link
Copy Markdown

I'm currently working on something similar, but I guess this would be a better solution. 👍

@astappiev
Copy link
Copy Markdown
Author

The only downside of these scripts is that they don't cover a scenario when a client is started after gluetun.

@AndaPlays
Copy link
Copy Markdown

@astappiev Looks good to me. The only thing I would appreciate is if we could add an option for Nmap to check whether the port is actually open. I'm on a couple of private trackers, and if my TCP port is filtered, I could get heat—or in the worst case—have my account banned.

I tried integrating it into my script and controlling the VPN via the control server, but Gluetun doesn't have an API for WireGuard yet.

@astappiev
Copy link
Copy Markdown
Author

I think it should be implemented as another script (as it is not client dependent), or even in the gluetun core.

@qdm12

This comment was marked as off-topic.

@qdm12

This comment was marked as off-topic.

@qdm12 qdm12 changed the title Add script to update qBittorrent peer port feat(extras/scripts): update qBittorrent peer port with optional authentication Nov 13, 2025
@AndaPlays

This comment was marked as off-topic.

@qdm12
Copy link
Copy Markdown
Owner

qdm12 commented Nov 14, 2025

@AndaPlays for this nmap command to succeed, I suppose you do need a program listening on the forwarded port right? What I'm thinking is to, when setting up port forwarding:

  1. start an ephemeral tcp server on the forwarded port / if the port is used already then don't that's fine too (udp is more complicated and not widely used by users so we'll skip that)
  2. check public-ip:port with a tcp dial (same as the nmap command)
  3. Report to debug logs it is open and finish the port forwarding setup process (I'm a maniac of logging problems only and avoid logging if things work correctly)

I'm going to mark our comments as off topic, would you please open an issue for this? Thanks!!

@monstermuffin
Copy link
Copy Markdown

Hey guys, I know it's not a native solution but this use case is exactly why I made qSticky. Been working very well and it doesn't matter what order things come up as it's a middleman between the two applications.

Copilot AI review requested due to automatic review settings January 15, 2026 08:43
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a shell script for updating qBittorrent's peer port configuration via its WebUI API, inspired by PR #2611 which added a similar script for Transmission. The script is designed to work with Gluetun's VPN port forwarding commands and supports optional authentication.

Changes:

  • Added a new shell script qbittorrent-port-update.sh with authentication support and flexible configuration options
  • Modified the Dockerfile to copy the script into the Docker image at /scripts/qbittorrent-port-update.sh

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 12 comments.

File Description
extras/scripts/qbittorrent-port-update.sh New script to update qBittorrent peer port, network interface, and address with optional authentication support
Dockerfile Added COPY instruction to include the script in the Docker image

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@qdm12 qdm12 force-pushed the master branch 3 times, most recently from 27f74e4 to fe3d4a9 Compare January 24, 2026 17:56
@qdm12 qdm12 force-pushed the master branch 2 times, most recently from d0247a1 to 0eeee5c Compare February 25, 2026 04:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +178
# second call to set the actual port, interface and address
wget ${WGET_OPTS} -qO- --post-data="json={\"listen_port\":$VPN_PORT,\"current_network_interface\":\"$VPN_INTERFACE\",\"current_interface_address\":\"$VPN_ADDRESS\"}" "$WEBUI_URL/v2/app/setPreferences"
if [ $? -ne 0 ]; then
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON payload is constructed via string interpolation without escaping VPN_INTERFACE / VPN_ADDRESS. If either contains a quote/backslash (or other unexpected characters), the request JSON will be invalid and could potentially change the intended preferences. Consider either JSON-escaping these values before building the payload, or strictly validating them against an allowlist pattern (interface name / IP literal / empty) before sending.

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +165
--server-response 2>&1 | \
grep -i "set-cookie:" | \
sed 's/.*set-cookie: //I;s/;.*//')

if [ -z "${cookie}" ]; then
echo "ERROR: Failed to authenticate with qBittorrent. Check username/password or verify WebUI is accessible"
exit 1
fi

# set cookie for future requests
WGET_OPTS="${WGET_OPTS} --header=Cookie:$cookie"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cookie is derived from potentially multiple Set-Cookie headers; if multiple lines are returned, the variable may contain newlines and later be appended into WGET_OPTS, producing an invalid --header argument. Consider constraining this to the specific cookie qBittorrent requires (e.g., first match for the session cookie) and/or stripping newlines before adding it to request headers.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still a problem now that is uses a cookie jar?

Comment on lines +91 to +96
if [ $# -lt 2 ] || [ -z "$2" ]; then
echo "Error: --iface requires a non-empty argument."
usage
exit 1
fi
VPN_INTERFACE="$2"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --iface option block rejects an explicitly empty value (--iface ""), but the usage text lists "" (any interface) as a valid example. Consider allowing an empty string by only erroring when the argument is missing (i.e., $# -lt 2), not when $2 is empty, and ensure downstream JSON generation handles the empty value correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +105
if [ $# -lt 2 ] || [ -z "$2" ]; then
echo "Error: --addr requires a non-empty argument."
usage
exit 1
fi
VPN_ADDRESS="$2"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --addr option block rejects an explicitly empty value (--addr ""), but the usage text lists "" (all addresses) as a valid example. Consider allowing an empty string by only erroring when the argument is missing (i.e., $# -lt 2), not when $2 is empty, and ensure the JSON payload remains valid when the address is empty.

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +125
--webui-port)
if [ $# -lt 2 ] || [ -z "$2" ]; then
echo "Error: --webui-port requires a non-empty argument."
usage
exit 1
fi
WEBUI_PORT="$2"
WEBUI_URL=$(build_default_url "$WEBUI_PORT")
shift 2
;;
--url)
if [ $# -lt 2 ] || [ -z "$2" ]; then
echo "Error: --url requires a non-empty argument."
usage
exit 1
fi
WEBUI_URL="$2"
shift 2
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help text says --webui-port is not compatible with --url (and vice-versa), but the parser currently allows both and whichever appears last silently wins. Please add an explicit validation after argument parsing to fail fast when both are provided, or otherwise define and document precedence.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

@blixten85
Copy link
Copy Markdown

blixten85 commented Mar 8, 2026

Look at hotio plex container and see how they have done for plex. Their plex container works with port forwarding.

This setup works for me. Whatever what’s going on under the hood I have no clue about.

  plex:
    container_name: plex
    image: ghcr.io/hotio/plex
    hostname: plex
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - UMASK=${UMASK}
      - TZ=${TZ}
      - PLEX_CLAIM_TOKEN=${PLEX_CLAIM_TOKEN}
      - PLEX_BETA_INSTALL=false
      - PLEX_PURGE_CODECS=false
      - VPN_ENABLED=true
      - VPN_CONF=wg0
      - VPN_PROVIDER=${HOTIO_VPN}
      - VPN_DNS=${VPN_DNS}
      - VPN_LAN_NETWORK=${VPN_LAN_NETWORK}
      - VPN_AUTO_PORT_FORWARD=true
      - VPN_PORT_REDIRECTS=32400/tcp
    volumes:
      - ${DOCKER_APP}/plex:/config
      - ${TV}:/tv
      - ${MOVIES}:/movies
      - ${RAM}:/transcode
    devices:
      - /dev/dri:/dev/dri
    networks:
      - media

@qdm12 qdm12 force-pushed the master branch 2 times, most recently from 2c06921 to 9a5995f Compare March 16, 2026 13:48
qdm12 and others added 2 commits March 29, 2026 01:29
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: 📌 Before next release Has to be done before the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants