Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: add env variable to run script in addition to saving port to file #26

Closed
zilexa opened this issue Jun 24, 2021 · 16 comments
Closed

Comments

@zilexa
Copy link

zilexa commented Jun 24, 2021

May I suggest to add a tiny feature?
Currently, when port forwarding with PIA has been configured, the port is saved to port.dat. Would it be possible to add a secondary action to that: run a bash script.
Allow users to add an environment variable in Compose that specifies the path of the .sh file. This way we do not need inotify, a seperate container etc. and users can use a script for their favourite torrent client to update the port.

For QBittorrent: #3 (comment)
For Transmission: #3 (comment)
For Deluge: #16 (comment)

This github has become a nice repository of interesting info :)

thrnz added a commit that referenced this issue Jun 25, 2021
When set a custom script can be run once a port is successfully forwarded.

See issue #26
@thrnz
Copy link
Owner

thrnz commented Jun 25, 2021

I've added PORT_SCRIPT that, when defined and the script is present, will run a script once a port is successfully forwarded. The forwarded port number will be passed as the first argument.

I briefly tested it with qBittorrent along with mounting the following script and it seemed to work as expected.

#!/bin/bash

port="$1"
QBT_USER=admin
QBT_PASS=xxxxxxxx
QBT_PORT=8080

echo "Setting qBittorrent port settings ($port)..."
# Very basic retry logic so we don't fail if qBittorrent isn't running yet
 while ! curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  --data "username=${QBT_USER}&password=${QBT_PASS}" \
  --cookie-jar /tmp/qb-cookies.txt \
  http://localhost:${QBT_PORT}/api/v2/auth/login
  do
    sleep 10
  done
  
curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  --data 'json={"listen_port": "'"$port"'"}' \
  --cookie /tmp/qb-cookies.txt \
  http://localhost:${QBT_PORT}/api/v2/app/setPreferences

echo "Qbittorrent port updated successfully ($port)..."

@zilexa
Copy link
Author

zilexa commented Jun 25, 2021

@thrnz you ROCK!
It would have taken me all weekend, lot's of trial and error to create such a script, without even the retry attributes.
I can confirm the script works here as well when I run it manually via bash portupdate-qbittorrent.sh.

However, when I:

  1. Via Portainer: remove docker-wireguard-pia and QB containers, and their non-persistent volumes and the docker-wireguard-pia image
  2. Add the env variable to the script, path is same as port.dat (/pia-shared/portupdate-qbittorrent.sh)
  3. Run docker-compose up -d

Then I add a torrent to QBittorrent, the orange connection status is shown in the bottom.
I wait 15min, but it stays that way. Eventually the added download becomes stalled.

As soon as I run the script manually, # of seeds and peers goes from 0 to a high number, download goes fast and after a minute or so, the orange icon turns green.

    environment:
      LOC: de-frankfurt
      LOCAL_NETWORK: 192.168.88.0/24
      PASS: mypassw
      PORT_FORWARDING: 1
      PORT_PERSIST: 0
      PORT_SCRIPT: /pia-shared/portupdate-qbittorrent.sh
      USER: myusername

I only added PORT_SCRIPT.

I also simply stopped QB container, then restarted your container and started QB again: it doesn't seem to update the listen port.
EDIT: after a restart and waiting much longer, the icon did turn green!

@zilexa
Copy link
Author

zilexa commented Jun 25, 2021

OK I can confirm:
When the container is created via compose, it doesn't work. Probably because Docker Compose will first create the vpn container, then start the QBittorrent container, simply because QB is in the other containers network.
I waited 15min.

When stopping QB and restarting the vpn container, I waited 10sec before starting QB container --> green icon.
(Even though the vpn container is started much earlier, like during creation via Compose, it does work).

It is not clear to me why it works after a restart, but not after creation.

@norsemangrey
Copy link

norsemangrey commented Sep 23, 2021

I've added PORT_SCRIPT that, when defined and the script is present, will run a script once a port is successfully forwarded. The forwarded port number will be passed as the first argument.

I briefly tested it with qBittorrent along with mounting the following script and it seemed to work as expected.

#!/bin/bash

port="$1"
QBT_USER=admin
QBT_PASS=xxxxxxxx
QBT_PORT=8080

echo "Setting qBittorrent port settings ($port)..."
# Very basic retry logic so we don't fail if qBittorrent isn't running yet
 while ! curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  --data "username=${QBT_USER}&password=${QBT_PASS}" \
  --cookie-jar /tmp/qb-cookies.txt \
  http://localhost:${QBT_PORT}/api/v2/auth/login
  do
    sleep 10
  done
  
curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  --data 'json={"listen_port": "'"$port"'"}' \
  --cookie /tmp/qb-cookies.txt \
  http://localhost:${QBT_PORT}/api/v2/app/setPreferences

echo "Qbittorrent port updated successfully ($port)..."

@thrnz I attempted to try out your scrip running it manually from within the VPN container. My qBittorrent container is up and running an using the VPN network, but I am not able to curl it from the VPN container (I get "Failed to connect to localhost port 8080 after 0 ms"). Is it something I might be missing?

@thrnz
Copy link
Owner

thrnz commented Sep 24, 2021

I've just manually ran that script against a qBittorrent 4.3.8 container that shares the network with the vpn container and it still seems to work as expected:

bash-5.1# ./test.sh 12345
Setting qBittorrent port settings (12345)...
Ok.Qbittorrent port updated successfully (12345)...

Nothing immediately comes to mind as to why it would be failing.

I don't suppose you've changed qBittorrent's webui to listen on another port, or to be https only or anything? Does curl http://localhost:8080 manage to connect to the webui? Does netstat -l from inside the vpn container show the webui? By default it'll be listed as listening on :::8080.

@Jorman
Copy link

Jorman commented Dec 24, 2021

Hi, I use a custom script to forward the port, before @thrnz implement the post-script function, so I want to share with you my script, too me seems that works, maybe someone can use it to create a new and better script.
Tell me if I'm if the script logic is wrong,
My very first idea is to run all in one single docker-compose file, this because in this way I can share the same network, "network_mode", so qBittorrent, docker-wireguard-pia and my qbittorrent_pia-wireguard_port-forward_port-helper docker in the same docker compose.
My qbittorrent_pia-wireguard_port-forward_port-helper basically contain only the script and the necessary variable to set-up qBittorrent port.
This's the script:

#!/bin/bash

trap 'exit 0' SIGTERM

sleep 10

############ CONFIGURATION ############
oldport=0
port=0
#######################################
qbt_host="http://localhost" # qbittorrent machine?
#qbt_host=$(getent hosts `hostname` | awk '{print $1}')
#qbt_username="admin" # Username for qbittorrent remote machine
#qbt_password="adminadmin" # Password for qbittorrent remote machine
#qbt_port="8081" # Port for qbittorrent webui
############ CONFIGURATION ############

############ FUNCTIONS ############
get_cookie () { # get the cookie
	echo "Getting cookie ..."
	qbt_cookie=$(curl --silent --fail --show-error \
		--header "Referer: ${qbt_host}:${qbt_port}" \
		--cookie-jar - \
		--request GET "${qbt_host}:${qbt_port}/api/v2/auth/login?username=${qbt_username}&password=${qbt_password}")
	echo "done"
}
############ FUNCTIONS ############

while true
do
	[ -r "/pia-shared/port.dat" ] && port=$(cat /pia-shared/port.dat)

	if [ $oldport -ne $port ]; then

		get_cookie

		echo "$qbt_cookie" | curl --silent --fail --show-error \
			--cookie - \
			--request POST "${qbt_host}:${qbt_port}/api/v2/app/setPreferences" \
			--data 'json={"listen_port": "'"$port"'"}'
		sleep 1

		oldport=$port
	fi
	sleep 30 &
	wait $!
done

As you can see, some configuration variables are unset, like #qbt_username, this because I set these variables from the docker compose.
Feel free to take the script and implement it.
I think I can make a new container with this new script calling function so

Ps, I always see the green connection from qBittorrent, but I've to set FIREWALL=0 on docker-wireguard-pia otherwise it doesn't seem to work.
And for example, if I check from https://www.yougetsignal.com/tools/open-ports/ the port seems to be closed but like I said the connection is green inside qBittorrent, any idea @thrnz ?

J

@thrnz
Copy link
Owner

thrnz commented Dec 28, 2021

If qBittorrent shows incoming TCP connections in the 'peers' tab (look for at least one BT peer with one of the 'flags' being an I) then incoming traffic to the forwarded port should be working as expected.

@Jorman
Copy link

Jorman commented Dec 28, 2021

Okay, I thought I had to open ports over my router and I already foresee many problems, but you know, networking is not my best
So, this's what I can see over peers tab
image
Just one curiosity, do you know why the port from outside seems always closed?

@zilexa
Copy link
Author

zilexa commented Dec 28, 2021

@Jorman, your container is connected via the network of Wireguard-pia. Did you test if the port is open via that container, for example via a terminal connection within the container?

If you are simply opening a browser on your host system and going to a website and filling in that port to test, you are simply testing if you opened a port in your router. You are not testing from within the tunnel. So your test is useless.

@Jorman
Copy link

Jorman commented Dec 28, 2021

Hi @zilexa
Ok, so when I try via browser I test the vpn ip that was assigned from pia, plus the port, this just to explain what I try, but like I already said i'm not so expert in Network, basic skills, not advanced.
Then, I tried to enter to docker and test one simple curl to ipinfo.io, and I see the vpn ip, and this's ok, but I really don't know how to test the port itself within the docker

@zilexa
Copy link
Author

zilexa commented Jul 29, 2022

This can be closed. It all works fine.

@zilexa zilexa closed this as completed Jul 29, 2022
@samuelcadieux
Copy link

In case that's useful to someone, here's the PORT_SCRIPT I used for transmission:

!/bin/bash

TRANSMISSION_RPC_ENDPOINT=localhost:9091/transmission/rpc
port="$1"

echo "Checking if tranmission is running..."
while ! curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  "$TRANSMISSION_RPC_ENDPOINT" > /dev/null
  do
    echo "Transmission is not running trying again in 10 seconds..."
    sleep 10
  done

echo "Resolving session id: $session_id..."
session_id=`curl --silent --retry 10 --retry-delay 15 --max-time 10 $TRANSMISSION_RPC_ENDPOINT | sed 's/.*<code>X-Transmission-Session-Id: \(.*\)<\/code>.*/\1/g'`

echo "Setting transmission port settings ($port) using session id: $session_id..."
curl --silent --retry 10 --retry-delay 15 --max-time 10 \
  -H "X-Transmission-Session-Id: $session_id" \
  -H 'Content-Type: text/plain;charset=UTF-8' \
  --data-raw "{\"arguments\":{\"peer-port\":$port},\"method\":\"session-set\"}" \
  "$TRANSMISSION_RPC_ENDPOINT"

@jacobonorte
Copy link

For someone less inclined,

The script goes inside the container and is run inside the container which passes the port to the QBitTorrent container right?

@zilexa
Copy link
Author

zilexa commented Apr 17, 2023

@jacobonorte no, see the documentation about the script. There is an env variable for your Docker Compose that points to the script. That should be a location in your volume mapping of your service.

See my compose file here and notice the volumes below this line:
https://github.com/zilexa/Homeserver/blob/9b5427a21d1c9e08b7dbe63c7f101e4004d95e62/docker/docker-compose.yml#L440

so my script is simply stored in $HOME/docker/vpn-proxy/pia-shared/ which is mapped via the Volumes section.
This means it is not stored directly inside the container. I can remove all containers and start fresh and the script would be mapped again automatically, without me having to do anything.

So I only do this once:

mkdir -p $HOME/docker/vpn-proxy/pia-shared
wget -O $HOME/docker/vpn-proxy/pia-shared/updateport-qb.sh https://raw.githubusercontent.com/zilexa/Homeserver/master/docker/vpn-proxy/pia-shared/updateport-qb.sh
chmod +x $HOME/docker/vpn-proxy/pia-shared/updateport-qb.sh

(note if you edit the script, it will loose its execution setting (chmod +x) so you need to do that again.
and after that I only use docker-compose up -d and never touch the script or copy/move it again.

@Sparklingx
Copy link

Sparklingx commented Jun 1, 2023

Im getting this error
copy pasted the script of @thrnz only changed the username,pass and webui port

image

EDIT: success . My solution: Had to add another volume: "/home/ggg/docker/pia/script.sh:/script.sh "

For Future reference if is someone having trouble , Here is my full docker-compose.yml file which is now working fine with webui port exposed in the internet. Change according to your needs.

services:
  vpn:
    image: thrnz/docker-wireguard-pia
    container_name: qbitwire
    volumes:
     - /home/gggg/docker/pia/pia:/pia
     - /home/gggg/docker/pia/pia-shared:/pia-shared
     - /home/gggg/docker/pia/script.sh:/script.sh
    cap_add:
     - NET_ADMIN
    environment:
     - LOC=swiss
     - USER=xxxxxxx
     - PASS=xxxxxxxx
     - KEEPALIVE=25
     - PORT_FORWARDING=1
     - PORT_SCRIPT=/script.sh

    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.default.disable_ipv6=1
      - net.ipv6.conf.all.disable_ipv6=1
      - net.ipv6.conf.lo.disable_ipv6=1
    networks:
      - vpn

  qbittorrent:
    image: qbittorrentofficial/qbittorrent-nox:latest
    container_name: qbitvpn
    network_mode: "service:vpn"
    environment:
      - PUID=1002
      - PGID=1002
      - TZ=Europe/London
      - QBT_WEBUI_PORT=8085
    volumes:
      - /home/ggg/docker/qbitvpn:/config
      - /home/ggg/Downloads/qbitvpn:/downloads
    depends_on:
      - vpn
    restart: always

  # Expose the webui port using socat
  reverse-proxy:
    image: alpine/socat
    container_name: qbitProxy
    depends_on:
      - vpn
    command: "TCP-LISTEN:8085,fork,reuseaddr TCP:vpn:8085"
    ports:
      - 8085:8085
    networks:
      - vpn
networks:
  vpn:

@goudarziha
Copy link

Im getting this error copy pasted the script of @thrnz only changed the username,pass and webui port

image

EDIT: success . My solution: Had to add another volume: "/home/ggg/docker/pia/script.sh:/script.sh "

For Future reference if is someone having trouble , Here is my full docker-compose.yml file which is now working fine with webui port exposed in the internet. Change according to your needs.

services:
  vpn:
    image: thrnz/docker-wireguard-pia
    container_name: qbitwire
    volumes:
     - /home/gggg/docker/pia/pia:/pia
     - /home/gggg/docker/pia/pia-shared:/pia-shared
     - /home/gggg/docker/pia/script.sh:/script.sh
    cap_add:
     - NET_ADMIN
    environment:
     - LOC=swiss
     - USER=xxxxxxx
     - PASS=xxxxxxxx
     - KEEPALIVE=25
     - PORT_FORWARDING=1
     - PORT_SCRIPT=/script.sh

    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.default.disable_ipv6=1
      - net.ipv6.conf.all.disable_ipv6=1
      - net.ipv6.conf.lo.disable_ipv6=1
    networks:
      - vpn

  qbittorrent:
    image: qbittorrentofficial/qbittorrent-nox:latest
    container_name: qbitvpn
    network_mode: "service:vpn"
    environment:
      - PUID=1002
      - PGID=1002
      - TZ=Europe/London
      - QBT_WEBUI_PORT=8085
    volumes:
      - /home/ggg/docker/qbitvpn:/config
      - /home/ggg/Downloads/qbitvpn:/downloads
    depends_on:
      - vpn
    restart: always

  # Expose the webui port using socat
  reverse-proxy:
    image: alpine/socat
    container_name: qbitProxy
    depends_on:
      - vpn
    command: "TCP-LISTEN:8085,fork,reuseaddr TCP:vpn:8085"
    ports:
      - 8085:8085
    networks:
      - vpn
networks:
  vpn:

you are a goat, I cant explain enough all the help this repo and all you smart people fixing it up. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants