diff --git a/docker_compose/serverhost/qbittorrent/10-torrent-init.sh b/docker_compose/serverhost/qbittorrent/10-torrent-init.sh index 20dfa22..9bd0476 100755 --- a/docker_compose/serverhost/qbittorrent/10-torrent-init.sh +++ b/docker_compose/serverhost/qbittorrent/10-torrent-init.sh @@ -7,18 +7,18 @@ cp -f /hostscripts/torrent_qbittorrent_complete.sh /config/ chmod +x /config/torrent_qbittorrent_complete.sh -#if ! command -v scp >/dev/null 2>&1; then -# echo "Install scp" -# -# for i in {1..12}; do -# if apk add --no-cache openssh-client; then -# break -# fi -# -# echo "Retry $i/12" -# sleep 5 -# done -#fi +if ! command -v scp >/dev/null 2>&1; then + echo "Install scp" + + for i in {1..12}; do + if apk add --no-cache openssh-client; then + break + fi + + echo "Retry $i/12" + sleep 5 + done +fi if [ ! -d /config/.venv ]; then echo "Generate venv" diff --git a/docker_compose/serverhost/qbittorrent/docker-compose.yaml b/docker_compose/serverhost/qbittorrent/docker-compose.yaml index eacaefa..970112f 100644 --- a/docker_compose/serverhost/qbittorrent/docker-compose.yaml +++ b/docker_compose/serverhost/qbittorrent/docker-compose.yaml @@ -1,8 +1,7 @@ services: - qbittorrent: - #image: "lscr.io/linuxserver/qbittorrent:latest" - build: . - container_name: "qbittorrent" + qbittorrent-private: + image: "lscr.io/linuxserver/qbittorrent:5.2.3" + container_name: "qbittorrent-private" environment: - PGID=1000 - TZ=Europe/Vienna @@ -16,8 +15,47 @@ services: volumes: - "./10-torrent-init.sh:/custom-cont-init.d/10-torrent-init.sh:ro" - - "./config:/config" + - "./qbittorrent-private:/config" - "/home/lucas/scripts/torrent:/hostscripts:ro" - - "/torrent/qbittorrent/downloads:/downloads" - - "/torrent/qbittorrent/torrents:/torrents" - - "/torrent/qbittorrent/watch:/watch" + - "/torrent/qbittorrent-private/downloads:/downloads-private" + - "/torrent/qbittorrent-private/torrents:/torrents" + qbittorrent-public: + image: "lscr.io/linuxserver/qbittorrent:5.2.3" + container_name: "qbittorrent-public" + environment: + - PGID=1000 + - TZ=Europe/Vienna + - PUID=1000 + - WEBUI_PORT=8080 + network_mode: "service:gluetun" + depends_on: + - gluetun + restart: "unless-stopped" + volumes: + - "./10-torrent-init.sh:/custom-cont-init.d/10-torrent-init.sh:ro" + - "./qbittorrent-public:/config" + - "/home/lucas/scripts/torrent:/hostscripts:ro" + - "/torrent/qbittorrent-public/downloads:/downloads-public" + - "/torrent/qbittorrent-public/torrents:/torrents" + gluetun: + image: qmcgaw/gluetun:latest + container_name: gluetun + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - 8082:8080 # qBittorrent WebUI + - 55662:55662 + - 55662:55662/udp + environment: + - VPN_SERVICE_PROVIDER=custom + - VPN_TYPE=wireguard + - SOCKS5_ENABLED=on + - HTTPPROXY=on + - SOCKSPROXY=on + - TZ=Europe/Vienna + volumes: + - ./gluetun:/gluetun/wireguard + diff --git a/docker_compose/serverhost/qbittorrent/gluetun/wg0.conf b/docker_compose/serverhost/qbittorrent/gluetun/wg0.conf new file mode 100644 index 0000000..a446913 --- /dev/null +++ b/docker_compose/serverhost/qbittorrent/gluetun/wg0.conf @@ -0,0 +1,12 @@ +# +# Use this configuration with WireGuard client +# +[Interface] +Address = 10.14.0.2/16 +PrivateKey = mKeDQdxtM1iFJS7WLlb2jPGabZIt3NkoA/nGCcNOU1I= +DNS = 162.252.172.57, 149.154.159.92 +[Peer] +PublicKey = dPZe8Jq3Hu0k07MDk+Y4+AS2XHSLYalyg91TSFXRYEA= +AllowedIPs = 0.0.0.0/0 +Endpoint = 87.249.133.4:51820 + diff --git a/docker_compose/serverhost/qbittorrent/qbittorrent-private/torrent_qbittorrent_complete.sh b/docker_compose/serverhost/qbittorrent/qbittorrent-private/torrent_qbittorrent_complete.sh new file mode 100755 index 0000000..63ae9ed --- /dev/null +++ b/docker_compose/serverhost/qbittorrent/qbittorrent-private/torrent_qbittorrent_complete.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +############################################################################### +# Description: +# qBittorrent external script that: +# 1. Receives torrent name, root path and category from qBittorrent. +# 2. Sends the torrent name to torrent_mqtt.py. +# 3. Copies the torrent contents to mediahost via SCP. +# 4. Logs all output to a timestamped logfile. +# +# Usage: +# torrent_complete.sh +# +# qBittorrent configuration: +# /home/lucas/scripts/serverhost/torrent_complete.sh "%N" "%R" "%L" +# +# Arguments: +# $1 Torrent name +# $2 Root path +# $3 Torrent category +# +# Log files: +# /home/lucas/.LOG/log_torrent_name_YYYY-MM-DD_HH-MM-SS.log +# +# Requirements: +# - bash +# - scp +# - SSH access to "mediahost" +# - /home/lucas/scripts/serverhost/torrent_mqtt.py +############################################################################### + +set -u + +SCRIPT_NAME="$(basename "$0")" + +############################################################################### +# Usage +############################################################################### + +usage() { + cat < + +Description: + Sends the torrent name to torrent_mqtt.py and copies the torrent + contents to mediahost. + +Arguments: + torrent_name Torrent name + root_path Torrent root path + category Torrent category + +Example: + $SCRIPT_NAME "Ubuntu 24.04" "/downloads/Ubuntu 24.04" "Linux" + +qBittorrent: + $SCRIPT_NAME "%N" "%R" "%L" + +EOF +} + +############################################################################### +# Check arguments +############################################################################### + +if [[ $# -ne 3 ]]; then + usage >&2 + exit 1 +fi + +TORRENT_NAME="$1" +ROOT_PATH="$2" +CATEGORY="$3" +if [[ "$CATEGORY" != *arr* && "$CATEGORY" != "mytorrents" ]]; then + + ############################################################################### + # Start + ############################################################################### + + echo "==================================================" + echo "Torrent transfer started" + echo "Date: $(date)" + echo "Script: $SCRIPT_NAME" + echo "Torrent name: $TORRENT_NAME" + echo "Root path: $ROOT_PATH" + echo "Category: $CATEGORY" + echo "==================================================" + + ############################################################################### + # Check for scp command + ############################################################################### + + if ! command -v scp >/dev/null 2>&1; then + echo "Install scp" + sed -i 's|http://|https://|g' /etc/apk/repositories + for i in {1..12}; do + if apk add --no-cache openssh-client; then + break + fi + + echo "Retry $i/12" + sleep 5 + done + fi + + + + ############################################################################### + # Send torrent name to MQTT script + ############################################################################### + + echo + echo "--- Sending torrent name to torrent_mqtt.py ---" + + /config/.venv/bin/python3 /config/torrent_mqtt.py "$TORRENT_NAME" + + MQTT_STATUS=$? + + echo "torrent_mqtt.py exit status: $MQTT_STATUS" + + ############################################################################### + # Check root path + ############################################################################### + + echo + echo "--- Checking root path ---" + + if [[ ! -d "$ROOT_PATH" ]]; then + echo "ERROR: Root path does not exist or is not a directory:" + echo " $ROOT_PATH" + exit 1 + fi + + echo "Root path exists." + + ############################################################################### + # Copy torrent to mediahost + ############################################################################### + + basename_root=$(basename "$ROOT_PATH") + echo $basename_root + if [ "$basename_root" = "downloads" ]; then + remote_dir="$TORRENT_NAME" + else + remote_dir="$basename_root" + fi + + echo + echo "--- Copying torrent to mediahost ---" + echo "Source: $ROOT_PATH" + echo "Destination: mediahost:/torrent/qbittorrent/mediahost/" + + ssh -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + lucas@mediahost "mkdir -p \"/torrent/qbittorrent/mediahost/$remote_dir\"" + SSH_STATUS=$? + scp -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -r "$ROOT_PATH"/. lucas@mediahost:/torrent/qbittorrent/mediahost/$remote_dir/ + SCP_STATUS=$? + + echo "scp exit status: $SCP_STATUS" + + ############################################################################### + # Result + ############################################################################### + + echo + echo "==================================================" + + if [[ $MQTT_STATUS -ne 0 ]]; then + echo "WARNING: torrent_mqtt.py failed." + fi + if [[ $SSH_STATUS -eq 0 ]]; then + echo "Target Dir generated" + else + echo "ERROR: Target dir generation failed." + fi + + if [[ $SCP_STATUS -eq 0 ]]; then + echo "Torrent transfer completed successfully." + else + echo "ERROR: Torrent transfer failed." + fi + + echo "Finished: $(date +'%y%m%d %H%M%Sr')" + echo "==================================================" +else + echo "ARR handled torrent: $(date +'%y%m%d %H%M%S'): $TORRENT_NAME" +fi + +# Return SCP's exit status to qBittorrent +exit 0 + diff --git a/docker_compose/serverhost/qbittorrent/qbittorrent-public/torrent_qbittorrent_complete.sh b/docker_compose/serverhost/qbittorrent/qbittorrent-public/torrent_qbittorrent_complete.sh new file mode 100755 index 0000000..63ae9ed --- /dev/null +++ b/docker_compose/serverhost/qbittorrent/qbittorrent-public/torrent_qbittorrent_complete.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +############################################################################### +# Description: +# qBittorrent external script that: +# 1. Receives torrent name, root path and category from qBittorrent. +# 2. Sends the torrent name to torrent_mqtt.py. +# 3. Copies the torrent contents to mediahost via SCP. +# 4. Logs all output to a timestamped logfile. +# +# Usage: +# torrent_complete.sh +# +# qBittorrent configuration: +# /home/lucas/scripts/serverhost/torrent_complete.sh "%N" "%R" "%L" +# +# Arguments: +# $1 Torrent name +# $2 Root path +# $3 Torrent category +# +# Log files: +# /home/lucas/.LOG/log_torrent_name_YYYY-MM-DD_HH-MM-SS.log +# +# Requirements: +# - bash +# - scp +# - SSH access to "mediahost" +# - /home/lucas/scripts/serverhost/torrent_mqtt.py +############################################################################### + +set -u + +SCRIPT_NAME="$(basename "$0")" + +############################################################################### +# Usage +############################################################################### + +usage() { + cat < + +Description: + Sends the torrent name to torrent_mqtt.py and copies the torrent + contents to mediahost. + +Arguments: + torrent_name Torrent name + root_path Torrent root path + category Torrent category + +Example: + $SCRIPT_NAME "Ubuntu 24.04" "/downloads/Ubuntu 24.04" "Linux" + +qBittorrent: + $SCRIPT_NAME "%N" "%R" "%L" + +EOF +} + +############################################################################### +# Check arguments +############################################################################### + +if [[ $# -ne 3 ]]; then + usage >&2 + exit 1 +fi + +TORRENT_NAME="$1" +ROOT_PATH="$2" +CATEGORY="$3" +if [[ "$CATEGORY" != *arr* && "$CATEGORY" != "mytorrents" ]]; then + + ############################################################################### + # Start + ############################################################################### + + echo "==================================================" + echo "Torrent transfer started" + echo "Date: $(date)" + echo "Script: $SCRIPT_NAME" + echo "Torrent name: $TORRENT_NAME" + echo "Root path: $ROOT_PATH" + echo "Category: $CATEGORY" + echo "==================================================" + + ############################################################################### + # Check for scp command + ############################################################################### + + if ! command -v scp >/dev/null 2>&1; then + echo "Install scp" + sed -i 's|http://|https://|g' /etc/apk/repositories + for i in {1..12}; do + if apk add --no-cache openssh-client; then + break + fi + + echo "Retry $i/12" + sleep 5 + done + fi + + + + ############################################################################### + # Send torrent name to MQTT script + ############################################################################### + + echo + echo "--- Sending torrent name to torrent_mqtt.py ---" + + /config/.venv/bin/python3 /config/torrent_mqtt.py "$TORRENT_NAME" + + MQTT_STATUS=$? + + echo "torrent_mqtt.py exit status: $MQTT_STATUS" + + ############################################################################### + # Check root path + ############################################################################### + + echo + echo "--- Checking root path ---" + + if [[ ! -d "$ROOT_PATH" ]]; then + echo "ERROR: Root path does not exist or is not a directory:" + echo " $ROOT_PATH" + exit 1 + fi + + echo "Root path exists." + + ############################################################################### + # Copy torrent to mediahost + ############################################################################### + + basename_root=$(basename "$ROOT_PATH") + echo $basename_root + if [ "$basename_root" = "downloads" ]; then + remote_dir="$TORRENT_NAME" + else + remote_dir="$basename_root" + fi + + echo + echo "--- Copying torrent to mediahost ---" + echo "Source: $ROOT_PATH" + echo "Destination: mediahost:/torrent/qbittorrent/mediahost/" + + ssh -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + lucas@mediahost "mkdir -p \"/torrent/qbittorrent/mediahost/$remote_dir\"" + SSH_STATUS=$? + scp -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -r "$ROOT_PATH"/. lucas@mediahost:/torrent/qbittorrent/mediahost/$remote_dir/ + SCP_STATUS=$? + + echo "scp exit status: $SCP_STATUS" + + ############################################################################### + # Result + ############################################################################### + + echo + echo "==================================================" + + if [[ $MQTT_STATUS -ne 0 ]]; then + echo "WARNING: torrent_mqtt.py failed." + fi + if [[ $SSH_STATUS -eq 0 ]]; then + echo "Target Dir generated" + else + echo "ERROR: Target dir generation failed." + fi + + if [[ $SCP_STATUS -eq 0 ]]; then + echo "Torrent transfer completed successfully." + else + echo "ERROR: Torrent transfer failed." + fi + + echo "Finished: $(date +'%y%m%d %H%M%Sr')" + echo "==================================================" +else + echo "ARR handled torrent: $(date +'%y%m%d %H%M%S'): $TORRENT_NAME" +fi + +# Return SCP's exit status to qBittorrent +exit 0 + diff --git a/utils/upgrade.sh b/utils/upgrade.sh index fb2ca23..b89fe4b 100755 --- a/utils/upgrade.sh +++ b/utils/upgrade.sh @@ -250,24 +250,24 @@ if command -v docker >/dev/null 2>&1; then echo "####################################################" case "$image" in - qbittorrent-qbittorrent:*) - echo "Updating custom qBittorrent image..." - ( - latest="$(curl -s https://api.github.com/repos/qbittorrent/qBittorrent/releases/latest | grep '"tag_name"' | cut -d '"' -f 4 | cut -d '-' -f2)" - current="$(docker exec -it qbittorrent /app/qbittorrent-nox -v | cut -d 'v' -f2)" - if [[ "$LATEST" != "$CURRENT" && "$BUILD" == "true" ]]; then - echo "New version available: $CURRENT -> $LATEST" - cd /docker/qbittorrent && - docker compose build --pull && - docker compose up -d - elif [[ "$LATEST" != "$CURRENT" ]]; then - echo "New version available: $CURRENT -> $LATEST" - echo "BUILD is turend off" - else - echo "No new version available: $CURRENT == $LATEST" - fi - ) - ;; +# qbittorrent-qbittorrent:*) +# echo "Updating custom qBittorrent image..." +# ( +# latest="$(curl -s https://api.github.com/repos/qbittorrent/qBittorrent/releases/latest | grep '"tag_name"' | cut -d '"' -f 4 | cut -d '-' -f2)" +# current="$(docker exec -it qbittorrent /app/qbittorrent-nox -v | cut -d 'v' -f2)" +# if [[ "$LATEST" != "$CURRENT" && "$BUILD" == "true" ]]; then +# echo "New version available: $CURRENT -> $LATEST" +# cd /docker/qbittorrent && +# docker compose build --pull && +# docker compose up -d +# elif [[ "$LATEST" != "$CURRENT" ]]; then +# echo "New version available: $CURRENT -> $LATEST" +# echo "BUILD is turend off" +# else +# echo "No new version available: $CURRENT == $LATEST" +# fi +# ) +# ;; nextcloud:*) docker pull "$image" docker exec -it nextcloud php occ app:update --all