From efef8c51325ca30cd9bc0a586fd0bd410c114eeb Mon Sep 17 00:00:00 2001 From: Kris Lamoureux Date: Sat, 21 Sep 2024 23:35:29 -0400 Subject: [PATCH] Add scripted gluetun VPN port forwarding - Add compose for gluetun and rtorrent services - Add runtime configuration options via SETTING_ prefix - Implement dynamic port discovery in entrypoint script - Add debug options for troubleshooting --- .gitignore | 1 + docker-compose.yml | 33 +++++++++++++ entrypoint.sh | 113 ++++++++++++++++++++++++++++++++++++++++++--- scratch/.gitignore | 2 + 4 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 docker-compose.yml create mode 100644 scratch/.gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dd40c54 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +volumes: + gluetun: + +services: + gluetun: + image: "qmcgaw/gluetun:${GLUETUN_VERSION}" + container_name: "${GLUETUN_NAME:-gluetun}" + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - gluetun:/gluetun + - "${GLUETUN_TMP:-./scratch/gluetun}:/tmp/gluetun" + environment: + - OPENVPN_USER=${VPN_USER} + - OPENVPN_PASSWORD=${VPN_PASSWORD} + - TZ=America/New_York + - VPN_PORT_FORWARDING=${VPN_PORTFORWARD:-off} + - VPN_SERVICE_PROVIDER=private internet access + - VPN_TYPE=openvpn + + rtorrent: + image: ${RTORRENT_IMAGE:-localhost/rtorrent}:${RTORRENT_VERSION:-latest} + container_name: "${RTORRENT_NAME:-rtorrent}" + network_mode: "service:gluetun" + depends_on: + - gluetun + environment: + - DEBUG=${DEBUG:-false} + - GLUETUN_FORWARD=${GLUETUN_FORWARD:-false} + volumes: + - "${GLUETUN_TMP:-./scratch/gluetun}:/tmp/gluetun:ro" diff --git a/entrypoint.sh b/entrypoint.sh index 70ba848..bbd042f 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,13 +1,29 @@ #!/bin/bash set -eu -# Polling interval -SLEEP_INTERVAL=${SLEEP_INTERVAL:-2} - # GID/UID USER_ID=${GUID:-1000} GROUP_ID=${PGID:-1000} +# Polling interval +SLEEP_INTERVAL=${SLEEP_INTERVAL:-2} + +# Gluetun config +GLUETUN_FORWARD=${GLUETUN_FORWARD:-false} +GLUETUN_TIMEOUT=${GLUETUN_TIMEOUT:-120} +GLUETUN_INITIAL_DELAY=${GLUETUN_INITIAL_DELAY:-5} + +# rtorrent runtime config +RTORRENT_RC=${RTORRENT_RC:-/home/rtorrent/.rtorrent.rc} +RTORRENT_PREFIX=${RTORRENT_PREFIX:-SETTING_} + +# Debug +DEBUG=${DEBUG:-false} +DEBUG_DIRECT=${DEBUG_DIRECT:-false} +if [ "$DEBUG" = "true" ]; then + set -x +fi + # Create group/user getent group rtorrent >/dev/null || groupadd -g "$GROUP_ID" rtorrent id -u rtorrent &>/dev/null || \ @@ -18,13 +34,95 @@ groupmod -o -g "$GROUP_ID" rtorrent usermod -o -u "$USER_ID" rtorrent &>/dev/null # Copy default config -if [ ! -e /home/rtorrent/.rtorrent.rc ]; then - cp /tmp/rtorrent.rc.template /home/rtorrent/.rtorrent.rc - chown rtorrent:rtorrent /home/rtorrent/.rtorrent.rc +if [ ! -e "$RTORRENT_RC" ]; then + cp /tmp/rtorrent.rc.template "$RTORRENT_RC" + chown rtorrent:rtorrent "$RTORRENT_RC" + echo "INFO: Copied template .rtorrent.rc" +fi + +# Optionally set forwarded port from Gluetun +if [ "$GLUETUN_FORWARD" = "true" ]; then + + # Is the port range already set? + if grep -q "^SETTING_network__port_range__set" < <(env); then + echo "[ERROR]: GLUETUN_FORWARD and SETTING_network__port_range__set is set" + exit 1 + fi + + # Check if GLUETUN_IP is already set + if [ -n "${GLUETUN_IP+x}" ]; then + echo "[ERROR]: GLUETUN_IP is already set" + exit 1 + fi + + sleep "$GLUETUN_INITIAL_DELAY" + GLUETUN_START_TIME="$(date +%s)" + + while true; do + GLUETUN_CURRENT_TIME="$(date +%s)" + GLUETUN_DIFF_TIME="$((GLUETUN_CURRENT_TIME - GLUETUN_START_TIME))" + + # Timeout check + if [ "$GLUETUN_DIFF_TIME" -ge "$GLUETUN_TIMEOUT" ]; then + echo "[ERROR]: Waited $DIFF_TIME/$GLUETUN_TIMEOUT seconds for Gluetun values" + exit 1 + fi + + # Check forwarded_port and IP + if [ -f /tmp/gluetun/forwarded_port ]; then + FORWARDED_PORT="$(cat /tmp/gluetun/forwarded_port)" + if [ -n "$FORWARDED_PORT" ] && [ "$FORWARDED_PORT" != "0" ]; then + if [ -f /tmp/gluetun/ip ]; then + GLUETUN_IP=$(cat /tmp/gluetun/ip) + if [ -n "$GLUETUN_IP" ] && [ "$GLUETUN_IP" != "" ]; then + break + fi + fi + fi + fi + + # Waiting + echo "Waiting ($GLUETUN_DIFF_TIME/$GLUETUN_TIMEOUT seconds) for Gluetun values" + sleep 5 + done + + # Set range + # shellcheck disable=SC2034 + export SETTING_network__port_range__set="${FORWARDED_PORT}-${FORWARDED_PORT}" +fi + +# Replace key/values +while IFS='=' read -r ENVVAR VALUE; do + if [[ $ENVVAR == ${RTORRENT_PREFIX}* ]]; then + KEY="${ENVVAR#"$RTORRENT_PREFIX"}" + KEY="${KEY//__/.}" + if ! grep -q "^${KEY}" "$RTORRENT_RC"; then + echo "[WARN]: \"$KEY\" does not exist in $RTORRENT_RC and was not updated" + else + if [ "$DEBUG" = "true" ]; then + echo "[DEBUG] Updating \"$KEY\" to \"$VALUE\"" + fi + sed -i "s|^${KEY}.*|${KEY} = ${VALUE}|" "$RTORRENT_RC" + fi + else + if [ "$DEBUG" = "true" ]; then + echo "[DEBUG] \"$ENVVAR\" doesn't have the prefix \"$RTORRENT_PREFIX\"" + fi + fi +done < <(env) + +# See final config if DEBUG +if [ "$DEBUG" = "true" ]; then + cat "$RTORRENT_RC" fi # Start rtorrent in a detached screen session -su - rtorrent -c "screen -dmS rtorrent rtorrent" & +# NOTE: Running without a screen isn't supported but might output config errors +if [ ! "$DEBUG_DIRECT" = "true" ]; then + su - rtorrent -c "screen -dmS rtorrent rtorrent" & +else + su - rtorrent -c "rtorrent" & +fi # Wait for the su process to finish wait $! @@ -36,5 +134,6 @@ RTORRENT_PID="$(pgrep -f "^rtorrent$")" trap 'su - rtorrent -c "kill -15 $RTORRENT_PID"' SIGTERM SIGINT # Wait for PID +[ "$DEBUG" = "true" ] && set +x while kill -0 "$RTORRENT_PID" 2>/dev/null; do sleep "$SLEEP_INTERVAL"; done exit 0 diff --git a/scratch/.gitignore b/scratch/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/scratch/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore