mirror of
https://github.com/haugene/docker-transmission-openvpn.git
synced 2025-08-06 22:37:18 +02:00
* Add Transmissionic Web UI & New Documentation (#2589) * Added step to build a .deb file to install and reduce image size (#2590) * Added step to build a .deb file to install and reduce image size * Fixed deb install incorrectly done * Check for update-port script existing instead of being executable (#2593) #2459 * Fixed TWC paths (#2600) * add docker build caching to workflow (#2609) * Privoxy eth0 fixes, healthcheck comparison tweak and start.sh update (#2610) * by checking for existence of default 127 address,healthcheck will never effectively run, as the non-default eth0 ip will never be matched * the comparison was not trimming off the port, thus healthcheck was always going to fail or denote a change when there may have been none * simplified the comparison (thanks @edgd1er ) * Strip double quotes from umask check (#2601) * Fix problem with enabled UFW with Random Ports (#2603) Fixing #2255 * move vpn config download to /config (#2592) * move vpn config download to /config * fix git safe dir permissions * cleanup vpn config clone * re-add zip dl, set git to default * use alpine:latest for TransmissionUIs build stage (#2573) * Update fetch-external-configs.sh removed duplicate bracket * Update to transmission 4.0.4 * Update configure-openvpn.sh --------- Co-authored-by: Anastasiya Polina Soyka <apsoyka@protonmail.com> Co-authored-by: Geoff <geoff@gapple.ca> Co-authored-by: ksurl <ksurl@users.noreply.github.com> Co-authored-by: HeavyGee <133152184+heavygee@users.noreply.github.com> Co-authored-by: WitchRecipe <77073792+WitchRecipe@users.noreply.github.com> Co-authored-by: Florian Kretschmer <19738301+Entepotenz@users.noreply.github.com>
349 lines
14 KiB
Bash
Executable File
349 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
##
|
|
# Get some initial setup out of the way.
|
|
##
|
|
|
|
set -e
|
|
|
|
source /etc/openvpn/utils.sh
|
|
|
|
if [[ -n "$REVISION" ]]; then
|
|
echo "Starting container with revision: $REVISION"
|
|
fi
|
|
|
|
#
|
|
# We have moved the default location of TRANSMISSION_HOME. Should be fully backwards compatible, but display an early warning.
|
|
# Will probably keep the compatibility for a long time but should nudge users to update their setup.
|
|
#
|
|
echo "TRANSMISSION_HOME is currently set to: ${TRANSMISSION_HOME}"
|
|
if [[ "${TRANSMISSION_HOME%/*}" != "/config" ]]; then
|
|
echo "WARNING: TRANSMISSION_HOME is not set to the default /config/transmission-home, this is not recommended."
|
|
echo "TRANSMISSION_HOME should be set to /config/transmission-home OR another custom directory on /config/<directory>"
|
|
echo "If you would like to migrate your existing TRANSMISSION_HOME, please stop the container, add volume /config and move the transmission-home directory there."
|
|
fi
|
|
#Old default transmission-home exists, use as fallback
|
|
if [ -d "/data/transmission-home" ]; then
|
|
TRANSMISSION_HOME="/data/transmission-home"
|
|
echo "WARNING: Deprecated. Found old default transmission-home folder at ${TRANSMISSION_HOME}, setting this as TRANSMISSION_HOME. This might break in future versions."
|
|
echo "We will fallback to this directory as long as the folder exists. Please consider moving it to /config/transmission-home"
|
|
fi
|
|
|
|
# If openvpn-pre-start.sh exists, run it
|
|
if [[ -x /scripts/openvpn-pre-start.sh ]]; then
|
|
echo "Executing /scripts/openvpn-pre-start.sh"
|
|
/scripts/openvpn-pre-start.sh "$@"
|
|
echo "/scripts/openvpn-pre-start.sh returned $?"
|
|
fi
|
|
|
|
# Allow for overriding the DNS used directly in the /etc/resolv.conf
|
|
if compgen -e | grep -q "OVERRIDE_DNS"; then
|
|
echo "One or more OVERRIDE_DNS addresses found. Will use them to overwrite /etc/resolv.conf"
|
|
echo "" > /etc/resolv.conf
|
|
for var in $(compgen -e | grep "OVERRIDE_DNS"); do
|
|
echo "nameserver $(printenv "$var")" >> /etc/resolv.conf
|
|
done
|
|
fi
|
|
|
|
# Test DNS resolution
|
|
if ! nslookup ${HEALTH_CHECK_HOST:-"google.com"} 1>/dev/null 2>&1; then
|
|
echo "WARNING: initial DNS resolution test failed"
|
|
fi
|
|
|
|
# If create_tun_device is set, create /dev/net/tun
|
|
if [[ "${CREATE_TUN_DEVICE,,}" == "true" ]] ; then
|
|
echo "Creating TUN device /dev/net/tun"
|
|
rm -f /dev/net/tun
|
|
mkdir -p /dev/net
|
|
mknod /dev/net/tun c 10 200
|
|
chmod 0666 /dev/net/tun
|
|
fi
|
|
|
|
##
|
|
# Configure OpenVPN.
|
|
# This basically means to figure out the config file to use as well as username/password
|
|
##
|
|
|
|
# If no OPENVPN_PROVIDER is given, we default to "custom" provider.
|
|
VPN_PROVIDER="${OPENVPN_PROVIDER:-custom}"
|
|
export VPN_PROVIDER="${VPN_PROVIDER,,}" # to lowercase
|
|
export VPN_PROVIDER_HOME="/etc/openvpn/${VPN_PROVIDER}"
|
|
mkdir -p "$VPN_PROVIDER_HOME"
|
|
|
|
# Make sure that we have enough information to start OpenVPN
|
|
if [[ -z $OPENVPN_CONFIG_URL ]] && [[ "${OPENVPN_PROVIDER}" == "**None**" ]] || [[ -z "${OPENVPN_PROVIDER-}" ]]; then
|
|
echo "ERROR: Cannot determine where to find your OpenVPN config. Both OPENVPN_CONFIG_URL and OPENVPN_PROVIDER is unset."
|
|
echo "You have to either provide a URL to the config you want to use, or set a configured provider that will download one for you."
|
|
echo "Exiting..." && exit 1
|
|
fi
|
|
echo "Using OpenVPN provider: ${VPN_PROVIDER^^}"
|
|
if [[ "${VPN_PROVIDER}" == "custom" ]]; then
|
|
if [[ -f $VPN_PROVIDER_HOME/default.ovpn ]]; then
|
|
CHOSEN_OPENVPN_CONFIG=$VPN_PROVIDER_HOME/default.ovpn
|
|
fi
|
|
elif [[ -n $OPENVPN_CONFIG_URL ]]; then
|
|
echo "Found URL to single OpenVPN config, will download and use it."
|
|
CHOSEN_OPENVPN_CONFIG=$VPN_PROVIDER_HOME/downloaded_config.ovpn
|
|
curl -o "$CHOSEN_OPENVPN_CONFIG" -sSL "$OPENVPN_CONFIG_URL"
|
|
fi
|
|
|
|
if [[ -z ${CHOSEN_OPENVPN_CONFIG} ]]; then
|
|
|
|
# Support pulling configs from external config sources
|
|
VPN_CONFIG_SOURCE="${VPN_CONFIG_SOURCE:-auto}"
|
|
VPN_CONFIG_SOURCE="${VPN_CONFIG_SOURCE,,}" # to lowercase
|
|
|
|
echo "Running with VPN_CONFIG_SOURCE ${VPN_CONFIG_SOURCE}"
|
|
|
|
if [[ "${VPN_CONFIG_SOURCE}" == "auto" ]]; then
|
|
if [[ -f $VPN_PROVIDER_HOME/configure-openvpn.sh ]]; then
|
|
echo "Provider ${VPN_PROVIDER^^} has a bundled setup script. Defaulting to internal config"
|
|
VPN_CONFIG_SOURCE=internal
|
|
elif [[ "${VPN_PROVIDER}" == "custom" ]]; then
|
|
echo "CUSTOM provider specified but not using default.ovpn, will try to find a valid config mounted to $VPN_PROVIDER_HOME"
|
|
VPN_CONFIG_SOURCE=custom
|
|
else
|
|
echo "No bundled config script found for ${VPN_PROVIDER^^}. Defaulting to external config"
|
|
VPN_CONFIG_SOURCE=external
|
|
fi
|
|
fi
|
|
|
|
if [[ "${VPN_CONFIG_SOURCE}" == "external" ]] && [[ "${VPN_PROVIDER}" != "custom" ]]; then
|
|
# shellcheck source=openvpn/fetch-external-configs.sh
|
|
./etc/openvpn/fetch-external-configs.sh
|
|
fi
|
|
|
|
if [[ -f $VPN_PROVIDER_HOME/configure-openvpn.sh ]]; then
|
|
echo "Executing setup script for $OPENVPN_PROVIDER"
|
|
# Preserve $PWD in case it changes when sourcing the script
|
|
pushd -n "$PWD" > /dev/null
|
|
# shellcheck source=/dev/null
|
|
. "$VPN_PROVIDER_HOME"/configure-openvpn.sh
|
|
# Restore previous PWD
|
|
popd > /dev/null
|
|
fi
|
|
fi
|
|
|
|
if [[ -z ${CHOSEN_OPENVPN_CONFIG:-""} ]]; then
|
|
# We still don't have a config. The user might have set a config in OPENVPN_CONFIG.
|
|
if [[ -n "${OPENVPN_CONFIG-}" ]]; then
|
|
# Read from file.
|
|
if [ -e /data/openvpn/OPENVPN_CONFIG ]; then
|
|
OPENVPN_CONFIG=$(cat /data/openvpn/OPENVPN_CONFIG)
|
|
fi
|
|
|
|
readarray -t OPENVPN_CONFIG_ARRAY <<< "${OPENVPN_CONFIG//,/$'\n'}"
|
|
|
|
## Trim leading and trailing spaces from all entries. Inefficient as all heck, but works like a champ.
|
|
for i in "${!OPENVPN_CONFIG_ARRAY[@]}"; do
|
|
OPENVPN_CONFIG_ARRAY[${i}]="${OPENVPN_CONFIG_ARRAY[${i}]#"${OPENVPN_CONFIG_ARRAY[${i}]%%[![:space:]]*}"}"
|
|
OPENVPN_CONFIG_ARRAY[${i}]="${OPENVPN_CONFIG_ARRAY[${i}]%"${OPENVPN_CONFIG_ARRAY[${i}]##*[![:space:]]}"}"
|
|
done
|
|
|
|
# If there were multiple configs (comma separated), select one of them.
|
|
if (( ${#OPENVPN_CONFIG_ARRAY[@]} > 1 )); then
|
|
if [[ ${OPENVPN_CONFIG_SEQUENTIAL:-false} == "false" ]]; then
|
|
# Select randomly.
|
|
OPENVPN_CONFIG_RANDOM=$((RANDOM%${#OPENVPN_CONFIG_ARRAY[@]}))
|
|
echo "${#OPENVPN_CONFIG_ARRAY[@]} servers found in OPENVPN_CONFIG, ${OPENVPN_CONFIG_ARRAY[${OPENVPN_CONFIG_RANDOM}]} chosen randomly"
|
|
OPENVPN_CONFIG="${OPENVPN_CONFIG_ARRAY[${OPENVPN_CONFIG_RANDOM}]}"
|
|
else
|
|
# Select sequentially.
|
|
echo "${#OPENVPN_CONFIG_ARRAY[@]} servers found in OPENVPN_CONFIG, ${OPENVPN_CONFIG_ARRAY[0]} chosen sequentially"
|
|
OPENVPN_CONFIG="${OPENVPN_CONFIG_ARRAY[0]}"
|
|
|
|
# Reorder and save to file.
|
|
OPENVPN_CONFIG_ARRAY=("${OPENVPN_CONFIG_ARRAY[@]:1}" "${OPENVPN_CONFIG_ARRAY[@]::1}")
|
|
mkdir -p /data/openvpn/
|
|
printf "%s," "${OPENVPN_CONFIG_ARRAY[@]}" | sed "s/,$//" > /data/openvpn/OPENVPN_CONFIG
|
|
fi
|
|
fi
|
|
|
|
# Check that the chosen config exists.
|
|
if [[ -f "${VPN_PROVIDER_HOME}/${OPENVPN_CONFIG}.ovpn" ]]; then
|
|
echo "Starting OpenVPN using config ${OPENVPN_CONFIG}.ovpn"
|
|
CHOSEN_OPENVPN_CONFIG="${VPN_PROVIDER_HOME}/${OPENVPN_CONFIG}.ovpn"
|
|
else
|
|
echo "Supplied config ${OPENVPN_CONFIG}.ovpn could not be found."
|
|
echo "Your options for this provider are:"
|
|
ls "${VPN_PROVIDER_HOME}" | grep .ovpn
|
|
echo "NB: Remember to not specify .ovpn as part of the config name."
|
|
exit 1 # No longer fall back to default. The user chose a specific config - we should use it or fail.
|
|
fi
|
|
else
|
|
echo "No VPN configuration provided. Using default."
|
|
CHOSEN_OPENVPN_CONFIG="${VPN_PROVIDER_HOME}/default.ovpn"
|
|
fi
|
|
fi
|
|
|
|
# log message and fail if attempting to mount config directly
|
|
if mountpoint -q "$CHOSEN_OPENVPN_CONFIG"; then
|
|
fatal_error "You're mounting a openvpn config directly, dont't do this it causes issues (see #2274). Mount the directory where the config is instead."
|
|
fi
|
|
|
|
MODIFY_CHOSEN_CONFIG="${MODIFY_CHOSEN_CONFIG:-true}"
|
|
# The config file we're supposed to use is chosen, modify it to fit this container setup
|
|
if [[ "${MODIFY_CHOSEN_CONFIG,,}" == "true" ]]; then
|
|
# shellcheck source=openvpn/modify-openvpn-config.sh
|
|
/etc/openvpn/modify-openvpn-config.sh "$CHOSEN_OPENVPN_CONFIG"
|
|
fi
|
|
|
|
# If openvpn-post-config.sh exists, run it
|
|
if [[ -x /scripts/openvpn-post-config.sh ]]; then
|
|
echo "Executing /scripts/openvpn-post-config.sh"
|
|
/scripts/openvpn-post-config.sh "$CHOSEN_OPENVPN_CONFIG"
|
|
echo "/scripts/openvpn-post-config.sh returned $?"
|
|
fi
|
|
|
|
mkdir -p /config
|
|
#Handle secrets if found
|
|
if [[ -f /run/secrets/openvpn_creds ]]; then
|
|
#write creds if no file or contents are not the same.
|
|
if [[ ! -f /config/openvpn-credentials.txt ]] || [[ "$(cat /run/secrets/openvpn_creds)" != "$(cat /config/openvpn-credentials.txt)" ]]; then
|
|
echo "Setting OpenVPN credentials..."
|
|
cp /run/secrets/openvpn_creds /config/openvpn-credentials.txt
|
|
fi
|
|
else
|
|
# add OpenVPN user/pass
|
|
if [[ "${OPENVPN_USERNAME}" == "**None**" ]] || [[ "${OPENVPN_PASSWORD}" == "**None**" ]]; then
|
|
if [[ ! -f /config/openvpn-credentials.txt ]]; then
|
|
echo "OpenVPN credentials not set. Exiting."
|
|
exit 1
|
|
fi
|
|
echo "Found existing OPENVPN credentials at /config/openvpn-credentials.txt"
|
|
else
|
|
echo "Setting OpenVPN credentials..."
|
|
echo -e "${OPENVPN_USERNAME}\n${OPENVPN_PASSWORD}" > /config/openvpn-credentials.txt
|
|
chmod 600 /config/openvpn-credentials.txt
|
|
fi
|
|
fi
|
|
|
|
if [[ -f /run/secrets/rpc_creds ]]; then
|
|
export TRANSMISSION_RPC_USERNAME=$(head -1 /run/secrets/rpc_creds)
|
|
export TRANSMISSION_RPC_PASSWORD=$(tail -1 /run/secrets/rpc_creds)
|
|
fi
|
|
echo "${TRANSMISSION_RPC_USERNAME}" > /config/transmission-credentials.txt
|
|
echo "${TRANSMISSION_RPC_PASSWORD}" >> /config/transmission-credentials.txt
|
|
|
|
# Persist transmission settings for use by transmission-daemon
|
|
export CONFIG="${CHOSEN_OPENVPN_CONFIG}"
|
|
python3 /etc/openvpn/persistEnvironment.py /etc/transmission/environment-variables.sh
|
|
|
|
TRANSMISSION_CONTROL_OPTS="--script-security 2 --route-up /etc/openvpn/tunnelUp.sh --route-pre-down /etc/openvpn/tunnelDown.sh"
|
|
|
|
## If we use UFW or the LOCAL_NETWORK we need to grab network config info
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]] || [[ -n "${LOCAL_NETWORK-}" ]]; then
|
|
eval $(/sbin/ip route list match 0.0.0.0 | awk '{if($5!="tun0"){print "GW="$3"\nINT="$5; exit}}')
|
|
## IF we use UFW_ALLOW_GW_NET along with ENABLE_UFW we need to know what our netmask CIDR is
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]] && [[ "${UFW_ALLOW_GW_NET,,}" == "true" ]]; then
|
|
eval $(/sbin/ip route list dev ${INT} | awk '{if($5=="link"){print "GW_CIDR="$1; exit}}')
|
|
fi
|
|
fi
|
|
|
|
## Open port to any address
|
|
function ufwAllowPort {
|
|
portNum=${1}
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]] && [[ -n "${portNum-}" ]]; then
|
|
echo "allowing ${portNum} through the firewall"
|
|
if [[ $portNum == *":"* ]];
|
|
then
|
|
ufw allow ${portNum}/tcp
|
|
ufw allow ${portNum}/udp
|
|
else
|
|
ufw allow ${portNum}
|
|
fi
|
|
fi
|
|
}
|
|
|
|
## Open port to specific address.
|
|
function ufwAllowPortLong {
|
|
portNum=${1}
|
|
sourceAddress=${2}
|
|
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]] && [[ -n "${portNum-}" ]] && [[ -n "${sourceAddress-}" ]]; then
|
|
echo "allowing ${sourceAddress} through the firewall to port ${portNum}"
|
|
ufw allow from ${sourceAddress} to any port ${portNum}
|
|
fi
|
|
}
|
|
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]]; then
|
|
if [[ "${UFW_DISABLE_IPTABLES_REJECT,,}" == "true" ]]; then
|
|
# A horrible hack to ufw to prevent it detecting the ability to limit and REJECT traffic
|
|
sed -i 's/return caps/return []/g' /usr/lib/python3/dist-packages/ufw/util.py
|
|
# force a rewrite on the enable below
|
|
echo "Disable and blank firewall"
|
|
ufw disable
|
|
echo "" > /etc/ufw/user.rules
|
|
fi
|
|
|
|
# Enable firewall
|
|
echo "enabling firewall"
|
|
sed -i -e s/IPV6=yes/IPV6=no/ /etc/default/ufw
|
|
ufw enable
|
|
|
|
|
|
# Ignore unset variables from here and out
|
|
# The UFW stuff should be revisited at some point...
|
|
set +u
|
|
|
|
if [[ "${TRANSMISSION_PEER_PORT_RANDOM_ON_START,,}" == "true" ]]; then
|
|
PEER_PORT="${TRANSMISSION_PEER_PORT_RANDOM_LOW}:${TRANSMISSION_PEER_PORT_RANDOM_HIGH}"
|
|
else
|
|
PEER_PORT="${TRANSMISSION_PEER_PORT}"
|
|
fi
|
|
|
|
ufwAllowPort ${PEER_PORT}
|
|
|
|
if [[ "${WEBPROXY_ENABLED,,}" == "true" ]]; then
|
|
ufwAllowPort ${WEBPROXY_PORT}
|
|
fi
|
|
if [[ "${UFW_ALLOW_GW_NET,,}" == "true" ]]; then
|
|
ufwAllowPortLong ${TRANSMISSION_RPC_PORT} ${GW_CIDR}
|
|
else
|
|
ufwAllowPortLong ${TRANSMISSION_RPC_PORT} ${GW}
|
|
fi
|
|
|
|
if [[ -n "${UFW_EXTRA_PORTS-}" ]]; then
|
|
for port in ${UFW_EXTRA_PORTS//,/ }; do
|
|
if [[ "${UFW_ALLOW_GW_NET,,}" == "true" ]]; then
|
|
ufwAllowPortLong ${port} ${GW_CIDR}
|
|
else
|
|
ufwAllowPortLong ${port} ${GW}
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "${LOCAL_NETWORK-}" ]]; then
|
|
if [[ -n "${GW-}" ]] && [[ -n "${INT-}" ]]; then
|
|
for localNet in ${LOCAL_NETWORK//,/ }; do
|
|
echo "adding route to local network ${localNet} via ${GW} dev ${INT}"
|
|
# Using `ip route replace` so that the command does not fail with
|
|
# `RTNETLINK answers: File exists` when the route already exists
|
|
/sbin/ip route replace "${localNet}" via "${GW}" dev "${INT}"
|
|
if [[ "${ENABLE_UFW,,}" == "true" ]]; then
|
|
ufwAllowPortLong ${TRANSMISSION_RPC_PORT} ${localNet}
|
|
if [[ -n "${UFW_EXTRA_PORTS-}" ]]; then
|
|
for port in ${UFW_EXTRA_PORTS//,/ }; do
|
|
ufwAllowPortLong ${port} ${localNet}
|
|
done
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
|
|
# If routes-post-start.sh exists, run it
|
|
if [[ -x /scripts/routes-post-start.sh ]]; then
|
|
echo "Executing /scripts/routes-post-start.sh"
|
|
/scripts/routes-post-start.sh "$@"
|
|
echo "/scripts/routes-post-start.sh returned $?"
|
|
fi
|
|
|
|
if [[ ${SELFHEAL:-false} != "false" ]]; then
|
|
/etc/scripts/selfheal.sh &
|
|
fi
|
|
|
|
# shellcheck disable=SC2086
|
|
exec openvpn ${TRANSMISSION_CONTROL_OPTS} ${OPENVPN_OPTS} --config "${CHOSEN_OPENVPN_CONFIG}"
|