Forked from trevordavies095/update_qbit_port.sh
Last active
February 24, 2024 11:31
-
-
Save socketbox/12be539ba0e26b76529e082c97bff53c to your computer and use it in GitHub Desktop.
Determine protonvpn port via gluetun and update qbittorrent
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Determine protonvpn port via gluetun and update qbittorrent | |
# | |
# Add the following to sudo crontab -e to run every 5 minutes | |
# */5 * * * * /bin/sh /path/to/update_qbit_port.sh | |
# For synology users, run the script as root via the task scheduler every 5 minutes. | |
QBITTORRENT_USER= # qbittorrent username | |
QBITTORRENT_PASS= # qbittorrent password | |
QBITTORRENT_PORT= | |
QBITTORRENT_SERVER=localhost # usually localhost if running all containers on the same machine | |
GLUETUN_SERVER=localhost # usually localhost if running all containers on the same machine | |
GLUETUN_PORT= | |
VPN_CT_NAME=gluetun | |
timestamp() { | |
date '+%Y-%m-%d %H:%M:%S' | |
} | |
findconfiguredport() { | |
curl -s --header "Referer: http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}" --cookie "$1" "http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}/api/v2/app/preferences" | jq -r '.listen_port' | |
} | |
findactiveport() { | |
curl -s "http://${GLUETUN_SERVER}:${GLUETUN_PORT}/v1/openvpn/portforwarded" | jq -r '.port' | |
} | |
getpublicip() { | |
curl -s "http://${GLUETUN_SERVER}:${GLUETUN_PORT}/v1/publicip/ip" | jq -r '.public_ip' | |
} | |
qbt_login() { | |
qbt_sid=$(curl -s -i --header "Referer: http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}" --data "username=${QBITTORRENT_USER}" --data-urlencode "password=${QBITTORRENT_PASS}" "http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}/api/v2/auth/login" | awk -F'SID=|;' '/set-cookie: SID/{print $2}') | |
return $? | |
} | |
qbt_changeport() { | |
curl -s -i --header "Referer: http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}" --cookie "$1" --data-urlencode "json={\"listen_port\":$2,\"random_port\":false,\"upnp\":false}" "http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}/api/v2/app/setPreferences" >/dev/null 2>&1 | |
return $? | |
} | |
qbt_checksid() { | |
if curl -s --header "Referer: http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}" --cookie "${qbt_sid}" "http://${QBITTORRENT_SERVER}:${QBITTORRENT_PORT}/api/v2/app/version" | grep -qi forbidden; then | |
return 1 | |
else | |
return 0 | |
fi | |
} | |
qbt_isreachable() { | |
nc -vw 5 ${QBITTORRENT_SERVER} ${QBITTORRENT_PORT} &>/dev/null 2>&1 | |
} | |
check_vpn_ct_health() { | |
while true; | |
do | |
response_code=$(curl -s -X GET -w "%{http_code}\n" "http://${GLUETUN_SERVER}:${GLUETUN_PORT}/v1/openvpn/portforwarded" -o /dev/null) | |
if [ $response_code -ne 200 ]; then | |
echo "$(timestamp) | VPN container ${VPN_CT_NAME} not answering..." | |
sleep 10 | |
else | |
echo "$(timestamp) | VPN container ${VPN_CT_NAME} in healthy state!" | |
break | |
fi | |
done | |
} | |
get_portmap() { | |
res=0 | |
public_ip=$(getpublicip) | |
echo "Debug--this is public_ip: $public_ip" | |
qbt_login | |
echo "Debug--this is qbt_sid: $qbt_sid" | |
if ! qbt_checksid; then | |
echo "$(timestamp) | qBittorrent Cookie invalid, getting new SessionID" | |
if ! qbt_login; then | |
echo "$(timestamp) | Failed getting new SessionID from qBittorrent" | |
return 1 | |
fi | |
else | |
echo "$(timestamp) | qBittorrent SessionID Ok!" | |
fi | |
configured_port=$(findconfiguredport "${qbt_sid}") | |
active_port=$(findactiveport) | |
echo "$(timestamp) | Public IP: ${public_ip}" | |
echo "$(timestamp) | Configured Port: ${configured_port}" | |
echo "$(timestamp) | Active Port: ${active_port}" | |
if [ "${configured_port}" != "${active_port}" ]; then | |
if qbt_changeport "${qbt_sid}" ${active_port}; then | |
echo "$(timestamp) | Port Changed to: $(findconfiguredport ${qbt_sid})" | |
else | |
echo "$(timestamp) | Port Change failed." | |
res=1 | |
fi | |
else | |
echo "$(timestamp) | Port OK (Act: ${active_port} Cfg: ${configured_port})" | |
fi | |
return $res | |
} | |
public_ip= | |
configured_port= | |
active_port= | |
qbt_sid= | |
# Wait for a healthy state on the VPN container | |
sleep 20 | |
check_vpn_ct_health | |
# check and possibly update the port | |
get_portmap | |
exit $? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Re-written for use in an Alpine-based container. A suitable service block/stanza in a docker compose file would look like the following:
Note the
network_mode
. It allows us to uselocalhost
as the host in requests to both thegluetun
andqbittorrent-nox
only if theqbittorrent-nox
container is also usingservice:gluetun
for its network.