From dc04aa9a4e5352275de243cb38f06acd34a2b72e Mon Sep 17 00:00:00 2001 From: "Arnaud G. GIBERT" Date: Fri, 23 May 2025 20:16:19 +0200 Subject: [PATCH] - Switch to config onboarding mode, - Enable AutoAdd plugin, - Add TotalTraffic plugin. --- Dockerfile | 98 ++++++++----------- ReadMe.txt | 3 +- compose.yaml | 1 + env.dist | 16 ++-- src/deluge/auth | 1 + src/deluge/autoadd.conf | 47 +++++++++ src/deluge/core.conf | 101 ++++++++++++++++++++ src/deluge/deluged.log | 0 src/deluge/deluged.pid | 0 src/deluge/plugins/TotalTraffic-0.5-fix.egg | Bin 0 -> 16857 bytes src/deluge/ssl/daemon.cert | 17 ++++ src/deluge/ssl/daemon.pkey | 28 ++++++ src/deluge/state/.safe_state_check | 0 src/deluge/stats.conf | 8 ++ src/deluge/totaltraffic.conf | 11 +++ src/deluge/web.conf | 24 +++++ src/deluge/web_plugin.conf | 8 ++ 17 files changed, 296 insertions(+), 67 deletions(-) create mode 100644 src/deluge/auth create mode 100644 src/deluge/autoadd.conf create mode 100644 src/deluge/core.conf create mode 100644 src/deluge/deluged.log create mode 100644 src/deluge/deluged.pid create mode 100644 src/deluge/plugins/TotalTraffic-0.5-fix.egg create mode 100644 src/deluge/ssl/daemon.cert create mode 100644 src/deluge/ssl/daemon.pkey create mode 100644 src/deluge/state/.safe_state_check create mode 100644 src/deluge/stats.conf create mode 100644 src/deluge/totaltraffic.conf create mode 100644 src/deluge/web.conf create mode 100644 src/deluge/web_plugin.conf diff --git a/Dockerfile b/Dockerfile index 77ab096..3e06a03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,7 @@ LABEL org.rx3.${IMG_NAME}.version=${IMG_VERSION} LABEL org.rx3.${IMG_NAME}.maintainer=${IMG_MAINTAINER} LABEL maintainer=${IMG_MAINTAINER} +ARG MODULE_PATH ARG DELUGE_PORT_DAEMON ARG DELUGE_PORT_WEB @@ -25,72 +26,53 @@ ARG DELUGE_CONFIG=${DELUGE_HOME} ARG DELUGE_CONFIG_TEMPLATE=${DELUGE_HOME}-template -#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -ARG DELUGED='#!/bin/bash \n\ - \n\ -usermod -u ${DELUGE_UID} deluge \n\ -groupmod -g ${DELUGE_GID} deluge \n\ - \n\ -if [[ ! -f '${DELUGE_CONFIG}'/auth ]] \n\ -then \n\ - cp -R '${DELUGE_CONFIG_TEMPLATE}'/* '${DELUGE_CONFIG}' \n\ - \n\ - deluged --config '${DELUGE_CONFIG}' \n\ - \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set allow_remote true \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set copy_torrent_file true \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set move_completed true \n\ - \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set listen_ports "[${DELUGE_PORT_BT_LOW},${DELUGE_PORT_BT_HIGH}]" \n\ - \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set download_location '${DELUGE_SPOOL}'/tmp \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set move_completed_path '${DELUGE_SPOOL}'/completed \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set plugins_location '${DELUGE_CONFIG}'/plugins \n\ - deluge-console --config '${DELUGE_CONFIG}' config --set torrentfiles_location '${DELUGE_SPOOL}'/torrent \n\ - \n\ - deluge-console --config '${DELUGE_CONFIG}' plugin --enable Label Stats WebUi \n\ - \n\ - deluge-console --config '${DELUGE_CONFIG}' halt \n\ - \n\ - echo "deluge:delugeadmin:10" >> '${DELUGE_CONFIG}'/auth \n\ - \n\ - echo "{\n \"file\": 1,\n \"format\": 1\n}{\n \"enabled\": true,\n \"port\": '${DELUGE_PORT_WEB}',\n \"ssl\": false\n}" > '${DELUGE_CONFIG}'/web_plugin.conf \n\ -fi \n\ - \n\ -for dir in torrent tmp completed \n\ -do \n\ - if [[ ! -d '${DELUGE_SPOOL}'/${dir} ]] \n\ - then \n\ - mkdir '${DELUGE_SPOOL}'/${dir} \n\ - fi \n\ -done \n\ - \n\ +#----------------------------------------------------------------------------------------------------------------------- +ARG DELUGED='#!/bin/bash \n\ + \n\ +usermod -u ${DELUGE_UID} deluge \n\ +groupmod -g ${DELUGE_GID} deluge \n\ + \n\ +if [[ ! -f '${DELUGE_CONFIG}'/auth ]] \n\ +then \n\ + cp -R '${DELUGE_CONFIG_TEMPLATE}'/* '${DELUGE_CONFIG}' \n\ + \n\ + sed -e "s/DELUGE_PORT_BT_LOW/${DELUGE_PORT_BT_LOW}/" -i '${DELUGE_CONFIG}'/core.conf \n\ + sed -e "s/DELUGE_PORT_BT_HIGH/${DELUGE_PORT_BT_HIGH}/" -i '${DELUGE_CONFIG}'/core.conf \n\ +fi \n\ + \n\ +for dir in torrent-auto torrent tmp completed \n\ +do \n\ + if [[ ! -d '${DELUGE_SPOOL}'/${dir} ]] \n\ + then \n\ + mkdir '${DELUGE_SPOOL}'/${dir} \n\ + fi \n\ +done \n\ + \n\ chown -R deluge:deluge '${DELUGE_LIB}' '${DELUGE_SPOOL} -#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#----------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -ARG DELUGED_INI='[program:deluged] \n\ -directory='${DELUGE_HOME}' \n\ -command=deluged --config '${DELUGE_CONFIG}' --do-not-daemonize \n\ -user=deluge \n\ +#----------------------------------------------------------------------------------------------------------------------- +ARG DELUGED_INI='[program:deluged] \n\ +directory='${DELUGE_HOME}' \n\ +command=deluged --config '${DELUGE_CONFIG}' --do-not-daemonize \n\ +user=deluge \n\ environment=HOME='${DELUGE_HOME} -#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#----------------------------------------------------------------------------------------------------------------------- -RUN urpmi.update -a \ - && urpmi --force deluge myip --no-recommends \ - && useradd --home-dir ${DELUGE_HOME} --password "" deluge \ - && mkdir ${DELUGE_SPOOL} \ - && echo -e "${DELUGED}" | sed -e "s/\`/'/g" -e 's/ *$//' > /etc/init.d/deluged \ - && chmod a+x /etc/init.d/deluged \ - && ln -s /etc/init.d/deluged /etc/rcD.d/S30deluged \ - && echo -e "${DELUGED_INI}" | sed -e "s/\`/'/g" -e 's/ *$//' > /etc/supervisord.d/deluged.ini \ - && deluged --config ${DELUGE_CONFIG_TEMPLATE} \ - && deluge-console --config ${DELUGE_CONFIG_TEMPLATE} halt +RUN urpmi.update -a \ + && urpmi --force deluge myip --no-recommends \ + && useradd --home-dir ${DELUGE_HOME} --password "" deluge \ + && mkdir ${DELUGE_SPOOL} \ + && echo -e "${DELUGED}" | sed -e "s/\`/'/g" -e 's/ *$//' > /etc/init.d/deluged \ + && chmod a+x /etc/init.d/deluged \ + && ln -s /etc/init.d/deluged /etc/rcD.d/S30deluged \ + && echo -e "${DELUGED_INI}" | sed -e "s/\`/'/g" -e 's/ *$//' > /etc/supervisord.d/deluged.ini + +ADD ${MODULE_PATH} ${DELUGE_CONFIG_TEMPLATE} EXPOSE ${DELUGE_PORT_DAEMON} EXPOSE ${DELUGE_PORT_WEB} - diff --git a/ReadMe.txt b/ReadMe.txt index b23c605..69b0083 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -6,7 +6,8 @@ This project aims to build a Deluge docker image. Features: - Curtently based on rx3-docker/server:1.2.2-mga9 image, - - Deluge Web plugin enabled. + - Enabled Deluge plugin: AutoAdd, Label, Stats & WebUi, + - Default Login/Password: deluge/delugeadmin diff --git a/compose.yaml b/compose.yaml index 345bcac..c3da529 100644 --- a/compose.yaml +++ b/compose.yaml @@ -21,6 +21,7 @@ services: IMG_MAINTAINER: ${P2P_IMG_MAINTAINER} IMG_FROM_URL: ${P2P_IMG_FROM_URL} + MODULE_PATH: ${P2P_MODULE_PATH} DELUGE_PORT_DAEMON: ${P2P_PORT_MAIN_INT} DELUGE_PORT_WEB: ${P2P_PORT_ADMIN_INT} diff --git a/env.dist b/env.dist index 716761a..f415fb0 100644 --- a/env.dist +++ b/env.dist @@ -18,7 +18,7 @@ ORG_URL_PREFIX="${ORG_REGISTRY}/${ORG_NAME}" #------------------------------------------------------------------------------- APPL_NAME="deluge" -APPL_NAME_FULL="Deluge Proxy" +APPL_NAME_FULL="Deluge" APPL_NAME_SHORT="deluge" APPL_ORG="rx3" APPL_VERSION="1.0.0" @@ -32,7 +32,7 @@ APPL_URL_PREFIX="${ORG_REGISTRY}/${APPL_ORG}" # User Settings #------------------------------------------------------------------------------- -APPL_ENV="0" +APPL_ENV="2" APPL_NAME_SHORT="vir" @@ -73,7 +73,7 @@ DOCKER_TOOLS_VOLUME=SINGLE # | Prefix | Name | URL Prefix | Name | Name Full | Version | URL Prefix | Name | Version | Name | Version | Ext | Int | Ext | Int | Name / Id | Name / Id | #------------------+----------+--------------------------+--------------------+------------------+-------------------------------+----------------------+--------------------+---------------+------------+--------------+------------+-------+-------+-------+-------+--------------+--------------+ -docker_service_add P2P peer-2-peer ${ORG_URL_PREFIX} deluge "Rx3-Docker/Deluge" ${APPL_VERSION}-mga9 ${ORG_URL_PREFIX} server 1.2.2-mga9 - - 8846 58846 8847 80 arnaud apache +docker_service_add P2P peer-2-peer ${ORG_URL_PREFIX} deluge "Rx3-Docker/Deluge" ${APPL_VERSION}-mga9 ${ORG_URL_PREFIX} server 1.2.2-mga9 - - 8846 58846 8847 80 mirror mirror @@ -86,10 +86,10 @@ SERVER_CROND_ENABLED="FALSE" P2P_SPOOL_INT="/var/spool/${P2P_IMG_NAME}" P2P_SPOOL_EXT=".${P2P_SPOOL_INT}" -P2P_PORT_BT_LOW=2500 -P2P_PORT_BT_HIGH=2501 +P2P_PORT_BT_LOW=3400 +P2P_PORT_BT_HIGH=3415 -NETWORK_SUBNET=10.10.34.8/30 -NETWORK_ADDRESS=10.10.34.9 -NETWORK_GATEWAY=10.10.34.10 +NETWORK_SUBNET=10.10.33.8/30 +NETWORK_ADDRESS=10.10.33.9 +NETWORK_GATEWAY=10.10.33.10 NETWORK_TABLE=4 diff --git a/src/deluge/auth b/src/deluge/auth new file mode 100644 index 0000000..ef02b7a --- /dev/null +++ b/src/deluge/auth @@ -0,0 +1 @@ +deluge:delugeadmin:10 diff --git a/src/deluge/autoadd.conf b/src/deluge/autoadd.conf new file mode 100644 index 0000000..8397070 --- /dev/null +++ b/src/deluge/autoadd.conf @@ -0,0 +1,47 @@ +{ + "file": 2, + "format": 1 +}{ + "next_id": 2, + "watchdirs": { + "1": { + "abspath": "/var/spool/deluge/torrent-auto", + "add_paused": true, + "add_paused_toggle": false, + "append_extension": ".added", + "append_extension_toggle": false, + "auto_managed": true, + "auto_managed_toggle": false, + "copy_torrent": "/var/spool/deluge/torrent", + "copy_torrent_toggle": true, + "delete_copy_torrent_toggle": false, + "download_location": "/var/spool/deluge/tmp", + "download_location_toggle": false, + "enabled": true, + "label": "", + "label_toggle": false, + "max_connections": 0, + "max_connections_toggle": false, + "max_download_speed": 0.0, + "max_download_speed_toggle": false, + "max_upload_slots": 0, + "max_upload_slots_toggle": false, + "max_upload_speed": 0.0, + "max_upload_speed_toggle": false, + "move_completed": true, + "move_completed_path": "/var/spool/deluge/completed", + "move_completed_toggle": false, + "owner": "deluge", + "path": "/var/spool/deluge/torrent-auto", + "queue_to_top": true, + "queue_to_top_toggle": false, + "remove_at_ratio": true, + "remove_at_ratio_toggle": false, + "seed_mode": false, + "stop_at_ratio": true, + "stop_at_ratio_toggle": false, + "stop_ratio": 0.0, + "stop_ratio_toggle": false + } + } +} \ No newline at end of file diff --git a/src/deluge/core.conf b/src/deluge/core.conf new file mode 100644 index 0000000..bb24272 --- /dev/null +++ b/src/deluge/core.conf @@ -0,0 +1,101 @@ +{ + "file": 1, + "format": 1 +}{ + "add_paused": false, + "allow_remote": true, + "auto_manage_prefer_seeds": false, + "auto_managed": true, + "cache_expiry": 60, + "cache_size": 1024, + "copy_torrent_file": true, + "daemon_port": 58846, + "del_copy_torrent_file": false, + "dht": true, + "dont_count_slow_torrents": false, + "download_location": "/var/spool/deluge/tmp", + "download_location_paths_list": [], + "enabled_plugins": [ + "AutoAdd", + "Label", + "Stats", + "TotalTraffic", + "WebUi" + ], + "enc_in_policy": 1, + "enc_level": 2, + "enc_out_policy": 1, + "geoip_db_location": "/usr/share/GeoIP/GeoIP.dat", + "ignore_limits_on_local_network": true, + "info_sent": 0.0, + "listen_interface": "", + "listen_ports": [ + DELUGE_PORT_BT_LOW, + DELUGE_PORT_BT_HIGH + ], + "listen_random_port": null, + "listen_reuse_port": true, + "listen_use_sys_port": false, + "lsd": true, + "max_active_downloading": 360, + "max_active_limit": 360, + "max_active_seeding": 360, + "max_connections_global": 320, + "max_connections_per_second": 96, + "max_connections_per_torrent": -1, + "max_download_speed": -1.0, + "max_download_speed_per_torrent": -1, + "max_half_open_connections": 96, + "max_upload_slots_global": 320, + "max_upload_slots_per_torrent": -1, + "max_upload_speed": -1.0, + "max_upload_speed_per_torrent": -1, + "move_completed": true, + "move_completed_path": "/var/spool/deluge/completed", + "move_completed_paths_list": [], + "natpmp": true, + "new_release_check": false, + "outgoing_interface": "", + "outgoing_ports": [ + 0, + 0 + ], + "path_chooser_accelerator_string": "Tab", + "path_chooser_auto_complete_enabled": true, + "path_chooser_max_popup_rows": 20, + "path_chooser_show_chooser_button_on_localhost": true, + "path_chooser_show_hidden_files": false, + "peer_tos": "0x00", + "plugins_location": "/var/lib/deluge/plugins", + "pre_allocate_storage": true, + "prioritize_first_last_pieces": false, + "proxy": { + "anonymous_mode": false, + "force_proxy": false, + "hostname": "", + "password": "", + "port": 8080, + "proxy_hostnames": true, + "proxy_peer_connections": true, + "proxy_tracker_connections": true, + "type": 0, + "username": "" + }, + "queue_new_to_top": false, + "random_outgoing_ports": true, + "random_port": false, + "rate_limit_ip_overhead": true, + "remove_seed_at_ratio": false, + "seed_time_limit": 180, + "seed_time_ratio_limit": 7.0, + "send_info": false, + "sequential_download": false, + "share_ratio_limit": 2.0, + "shared": false, + "stop_seed_at_ratio": false, + "stop_seed_ratio": 2.0, + "super_seeding": false, + "torrentfiles_location": "/var/spool/deluge/torrent", + "upnp": true, + "utpex": true +} \ No newline at end of file diff --git a/src/deluge/deluged.log b/src/deluge/deluged.log new file mode 100644 index 0000000..e69de29 diff --git a/src/deluge/deluged.pid b/src/deluge/deluged.pid new file mode 100644 index 0000000..e69de29 diff --git a/src/deluge/plugins/TotalTraffic-0.5-fix.egg b/src/deluge/plugins/TotalTraffic-0.5-fix.egg new file mode 100644 index 0000000000000000000000000000000000000000..ffbc99322956552b41c37ed68e6499ed14f14a50 GIT binary patch literal 16857 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