├── .dockerignore
├── rootfs
├── service
│ ├── nginx
│ │ └── run
│ ├── php5-fpm
│ │ └── run
│ ├── rtorrent
│ │ ├── finish
│ │ └── run
│ ├── .s6-svscan
│ │ └── finish
│ └── healthcheck
│ │ └── run
└── usr
│ └── local
│ └── bin
│ └── docktorrent
├── s6-1.1.3.2-musl-static.tar.xz
├── config
├── nginx
│ └── default
├── rutorrent
│ └── config.php
└── rtorrent
│ └── .rtorrent.rc
├── README.md
└── Dockerfile
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 |
--------------------------------------------------------------------------------
/rootfs/service/nginx/run:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | service nginx start
4 |
--------------------------------------------------------------------------------
/rootfs/service/php5-fpm/run:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | service php5-fpm start
4 |
--------------------------------------------------------------------------------
/s6-1.1.3.2-musl-static.tar.xz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kfei/docktorrent/HEAD/s6-1.1.3.2-musl-static.tar.xz
--------------------------------------------------------------------------------
/rootfs/service/rtorrent/finish:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Send SIGTERM to all remaining services if it's a `docker stop`
4 | [ -e /tmp/is-docker-stop ] && {
5 | rm -f /tmp/is-docker-stop
6 | s6-svscanctl -t /service
7 | }
8 |
--------------------------------------------------------------------------------
/rootfs/service/.s6-svscan/finish:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo
4 | echo "Shutting down..."
5 |
6 | # Tell rTorrent this is a `docker stop`,
7 | # which means it does not have to auto restart
8 | touch /tmp/is-docker-stop
9 |
10 | # Kind of workaround...
11 | touch /etc/leapsecs.dat
12 | exec s6-svwait -d /service/rtorrent
13 |
--------------------------------------------------------------------------------
/rootfs/service/rtorrent/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Checking the lock
4 | if [ -f /rtorrent/.session/rtorrent.lock ]; then
5 | echo
6 | prompt="The rTorrent session lock is detected, it can be a result of an \n"
7 | prompt="${prompt}unexpected exit or other running rTorrent instance.\n"
8 | echo -e ${prompt}
9 | prompt="Remove lock and continue anyway? [y/N] "
10 | read -r -p "${prompt}" response
11 | response=${response,,}
12 | if [[ $response =~ ^(yes|y)$ ]]; then
13 | rm -f /rtorrent/.session/rtorrent.lock
14 | else
15 | s6-svscanctl -t /service
16 | fi
17 | fi
18 |
19 | # Turn to rTorrent
20 | exec rtorrent
21 |
--------------------------------------------------------------------------------
/rootfs/service/healthcheck/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ################################################
3 | # rtorrent-healthcheck #
4 | # Monitor rtorrent and restart it if it hangs. #
5 | ################################################
6 |
7 | # Interval, in seconds
8 | interval=30
9 |
10 | # Delay start time, in seconds
11 | delay_start=1200
12 |
13 | # Times of retry
14 | retry=3
15 |
16 | # End of configuration
17 |
18 | # We sleep first to avoid any race when starting for the first time.
19 | sleep $delay_start
20 |
21 | while true
22 | do
23 | # Capture the HTTP status code when we send an XML request. If the API is
24 | # available, we should get a 200 OK. When it's not, we generally get a
25 | # Gateway Timeout from Nginx - but we aren't specifically looking for that.
26 | status_code=$(
27 | curl --silent \
28 | --data '' \
29 | --write-out '%{http_code}' \
30 | --output /dev/null \
31 | --retry $retry \
32 | http://localhost/RPC2 \
33 | )
34 | if [ "$status_code" = "200" ]
35 | then
36 | sleep $interval
37 | else
38 | rm -f /rtorrent/.session/rtorrent.lock
39 | s6-svc -k /service/rtorrent
40 | sleep $delay_start
41 | fi
42 | done
43 |
44 |
--------------------------------------------------------------------------------
/config/nginx/default:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 |
4 | root /usr/share/nginx/html/rutorrent;
5 | index index.html index.php;
6 |
7 | server_name "docktorrent";
8 |
9 | # Only localhost and networks passed by `-e AUTH_OFF` are allowed to access
10 | # resources unauthenticated.
11 | satisfy any;
12 | allow 127.0.0.1;
13 | deny all;
14 | auth_basic "Login Required";
15 | auth_basic_user_file /usr/share/nginx/html/rutorrent/.htpasswd;
16 |
17 | location /RPC2 {
18 | include scgi_params;
19 | scgi_send_timeout 10s;
20 | scgi_read_timeout 10s;
21 | scgi_pass unix:/tmp/rpc.socket;
22 | }
23 |
24 | location / {
25 | try_files $uri $uri/ /index.html;
26 | }
27 |
28 | location ~ \.php$ {
29 | fastcgi_split_path_info ^(.+\.php)(/.+)$;
30 | # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
31 |
32 | fastcgi_pass unix:/var/run/php5-fpm.sock;
33 | fastcgi_index index.php;
34 | include fastcgi.conf;
35 | }
36 | }
37 |
38 | # HTTPS server
39 | #
40 | # server {
41 | # listen 443;
42 | # server_name localhost;
43 | #
44 | # root html;
45 | # index index.html index.htm;
46 | #
47 | # ssl on;
48 | # ssl_certificate cert.pem;
49 | # ssl_certificate_key cert.key;
50 | #
51 | # ssl_session_timeout 5m;
52 | #
53 | # ssl_protocols SSLv3 TLSv1;
54 | # ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
55 | # ssl_prefer_server_ciphers on;
56 | #
57 | # location / {
58 | # try_files $uri $uri/ =404;
59 | # }
60 | # }
61 |
--------------------------------------------------------------------------------
/rootfs/usr/local/bin/docktorrent:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create working directories if not exists
4 | mkdir -p /rtorrent/{downloads,watch,.session,rutorrent/user-profiles,rutorrent/user-profiles/torrents}
5 |
6 | # Change permission to ruTorrent's webserver user
7 | chown -R www-data:www-data /rtorrent
8 |
9 | # Override rTorrent settings
10 | [ "${IP}" ] && {
11 | sed -i '/^ip =/d' /root/.rtorrent.rc
12 | echo "ip = ${IP}" >> /root/.rtorrent.rc
13 | }
14 | [ "${MAX_PEERS}" ] && {
15 | sed -i '/^max_peers =/d' /root/.rtorrent.rc
16 | echo "max_peers = ${MAX_PEERS}" >> /root/.rtorrent.rc
17 | }
18 | [ "${MAX_PEERS_SEED}" ] && {
19 | sed -i '/^max_peers_seed =/d' /root/.rtorrent.rc
20 | echo "max_peers_seed = ${MAX_PEERS_SEED}" >> /root/.rtorrent.rc
21 | }
22 | [ "${MAX_UPLOADS}" ] && {
23 | sed -i '/^max_uploads =/d' /root/.rtorrent.rc
24 | echo "max_uploads = ${MAX_UPLOADS}" >> /root/.rtorrent.rc
25 | }
26 | [ "${DOWNLOAD_RATE}" ] && {
27 | sed -i '/^download_rate =/d' /root/.rtorrent.rc
28 | echo "download_rate = ${DOWNLOAD_RATE}" >> /root/.rtorrent.rc
29 | }
30 | [ "${UPLOAD_RATE}" ] && {
31 | sed -i '/^upload_rate =/d' /root/.rtorrent.rc
32 | echo "upload_rate = ${UPLOAD_RATE}" >> /root/.rtorrent.rc
33 | }
34 |
35 | # Turn off all logs
36 | [ "${LOGS_OFF}" == "yes" ] || [ "${LOGS_OFF}" == "y" ] && {
37 | sed -i '/^log./d' /root/.rtorrent.rc
38 | sed -i 's/\/var\/log\/nginx\/access.log;/\/dev\/null;/g' /etc/nginx/nginx.conf
39 | sed -i 's/\/var\/log\/nginx\/error.log;/\/dev\/null crit;/g' /etc/nginx/nginx.conf
40 | sed -i 's/^error_log = .*log/error_log = \/dev\/null/g' /etc/php5/fpm/php-fpm.conf
41 | }
42 |
43 | # Turn off authentication
44 | [ "${AUTH_OFF}" ] && {
45 | sed -i '/allow 127.0.0.1/a allow '${AUTH_OFF}';' /etc/nginx/sites-enabled/default
46 | }
47 |
48 | # Use s6 to supervise all services
49 | exec /usr/bin/s6-svscan -t0 /service
50 |
--------------------------------------------------------------------------------
/config/rutorrent/config.php:
--------------------------------------------------------------------------------
1 | rtorrent link through unix domain socket
34 | // (scgi_local in rtorrent conf file), change variables
35 | // above to something like this:
36 | $scgi_port = 0;
37 | $scgi_host = "unix:///tmp/rpc.socket";
38 |
39 | $XMLRPCMountPoint = "/RPC2"; // DO NOT DELETE THIS LINE!!! DO NOT COMMENT THIS LINE!!!
40 |
41 | $pathToExternals = array(
42 | "php" => '', // Something like /usr/bin/php. If empty, will be found in PATH.
43 | "curl" => '/usr/local/bin/curl', // Something like /usr/bin/curl. If empty, will be found in PATH.
44 | "gzip" => '', // Something like /usr/bin/gzip. If empty, will be found in PATH.
45 | "id" => '', // Something like /usr/bin/id. If empty, will be found in PATH.
46 | "stat" => '', // Something like /usr/bin/stat. If empty, will be found in PATH.
47 | );
48 |
49 | $localhosts = array( // list of local interfaces
50 | "127.0.0.1",
51 | "localhost",
52 | );
53 |
54 | $profilePath = '/rtorrent/rutorrent/user-profiles'; // Path to user profiles
55 | $profileMask = 0777; // Mask for files and directory creation in user profiles.
56 | // Both Webserver and rtorrent users must have read-write access to it.
57 | // For example, if Webserver and rtorrent users are in the same group then the value may be 0770.
58 |
59 | $tempDirectory = null; // Temp directory. Absolute path with trail slash. If null, then autodetect will be used.
60 |
--------------------------------------------------------------------------------
/config/rtorrent/.rtorrent.rc:
--------------------------------------------------------------------------------
1 | # This is an example resource file for rTorrent. Copy to
2 | # ~/.rtorrent.rc and enable/modify the options as needed. Remember to
3 | # uncomment the options you wish to enable.
4 |
5 | # Maximum and minimum number of peers to connect to per torrent.
6 | #min_peers = 40
7 | max_peers = 64
8 |
9 | # Same as above but for seeding completed torrents (-1 = same as downloading)
10 | #min_peers_seed = 10
11 | max_peers_seed = 8
12 |
13 | # Maximum number of simultanious uploads per torrent.
14 | max_uploads = 16
15 |
16 | # Global upload and download rate in KiB. "0" for unlimited.
17 | #download_rate = 0
18 | upload_rate = 512
19 |
20 | # Default directory to save the downloaded torrents.
21 | directory = /rtorrent/downloads
22 |
23 | system.method.insert = d.get_finished_dir,simple,"cat=/rtorrent/finished/,$d.get_custom1="
24 | system.method.set_key = event.download.finished,move_complete,"d.set_directory=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.get_base_path=,$d.get_finished_dir="
25 |
26 | # Default session directory. Make sure you don't run multiple instance
27 | # of rtorrent using the same session directory. Perhaps using a
28 | # relative path?
29 | session = /rtorrent/.session
30 |
31 | # Watch a directory for new torrents, and stop those that have been
32 | # deleted.
33 | schedule = watch_directory,5,5,load_start=/rtorrent/watch/*.torrent
34 | schedule = untied_directory,5,5,stop_untied=
35 |
36 | # Close torrents when diskspace is low.
37 | schedule = low_diskspace,5,60,close_low_diskspace=100M
38 |
39 | # The ip address reported to the tracker.
40 | #ip = 127.0.0.1
41 | #ip = rakshasa.no
42 |
43 | # The ip address the listening socket and outgoing connections is
44 | # bound to.
45 | #bind = 127.0.0.1
46 | #bind = rakshasa.no
47 |
48 | # Port range to use for listening.
49 | port_range = 45566-45566
50 |
51 | # Start opening ports at a random position within the port range.
52 | #port_random = no
53 |
54 | # Check hash for finished torrents. Might be usefull until the bug is
55 | # fixed that causes lack of diskspace not to be properly reported.
56 | check_hash = yes
57 |
58 | # Set whether the client should try to connect to UDP trackers.
59 | use_udp_trackers = yes
60 |
61 | # Alternative calls to bind and ip that should handle dynamic ip's.
62 | #schedule = ip_tick,0,1800,ip=rakshasa.no
63 | #schedule = bind_tick,0,1800,bind=rakshasa.no
64 |
65 | # Encryption options, set to none (default) or any combination of the following:
66 | # allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
67 | #
68 | # The example value allows incoming encrypted connections, starts unencrypted
69 | # outgoing connections but retries with encryption if they fail, preferring
70 | # plaintext to RC4 encryption after the encrypted handshake
71 | #
72 | encryption = allow_incoming,try_outgoing,enable_retry
73 |
74 | # Enable DHT support for trackerless torrents or when all trackers are down.
75 | # May be set to "disable" (completely disable DHT), "off" (do not start DHT),
76 | # "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
77 | # The default is "off". For DHT to work, a session directory must be defined.
78 | #
79 | dht = on
80 |
81 | # UDP port to use for DHT.
82 | #
83 | dht_port = 9527
84 |
85 | # Enable peer exchange (for torrents not marked private)
86 | #
87 | peer_exchange = yes
88 |
89 | # Preallocate files; reduces defragmentation on filesystems
90 | system.file_allocate.set = yes
91 |
92 | # For ruTorrent
93 | execute_nothrow = rm,/tmp/rpc.socket
94 | scgi_local = /tmp/rpc.socket
95 | schedule = chmod,0,0,"execute=chmod,777,/tmp/rpc.socket"
96 |
97 | # Encoding
98 | encoding_list = UTF-8
99 |
100 | # Log to file
101 | log.open_file = "rtorrent", /var/log/rtorrent.log
102 | log.add_output = "debug", "rtorrent"
103 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 |
5 | # docktorrent
6 |
7 | Using [Docker](https://www.docker.com/),
8 | [rTorrent](http://rakshasa.github.io/rtorrent/) and
9 | [ruTorrent](https://github.com/Novik/ruTorrent) to run a full-featured
10 | BitTorrent box.
11 |
12 | ## Highlights
13 |
14 | - All-in-one Docker container, build once and run everywhere.
15 | - Newest version of rTorrent and ruTorrent, with support of DHT and
16 | asynchronous DNS which will results in a more responsive rTorrent.
17 | - Enable all useful ruTorrent plugins by default.
18 | - Get a working BitTorrent box in less than 3 minutes, give it a quick try
19 | and tune the configs later.
20 | - rTorrent will automatically restarts on crash or freeze.
21 | - No more boring installation, also keep your OS in a clean state.
22 |
23 | ## Quick Start
24 |
25 | Clone this repository and build the image locally:
26 | ```bash
27 | git clone https://github.com/kfei/docktorrent
28 | cd docktorrent
29 | docker build -t docktorrent .
30 | ```
31 |
32 | The building process may take some time. You can just pull the latest image
33 | from Docker Hub:
34 | ```bash
35 | docker pull kfei/docktorrent
36 | ```
37 |
38 | After the image is built or pulled, run the docktorrent container, for example:
39 | ```bash
40 | docker run -it \
41 | -p 80:80 -p 45566:45566 -p 9527:9527/udp \
42 | --dns 8.8.8.8 \
43 | -v /data-store:/rtorrent \
44 | -e UPLOAD_RATE=1024 \
45 | kfei/docktorrent # Or just `docktorrent` for locally built image
46 | ```
47 | Note that:
48 | - The exposed ports are required for ruTorrent web interface, rTorrent
49 | listening and the DHT protocol according to the default `.rtorrent.rc`.
50 | - The `--dns 8.8.8.8` argument is optional but recommended. It seems like the
51 | current version of rTorrent still has some [DNS
52 | issues](https://github.com/rakshasa/rtorrent/issues/180), using Google's
53 | DNS may help.
54 | - The `/data-store` volume is for all downloads, torrents and session data,
55 | just make sure the disk space is enough.
56 | - Override the `upload_rate` setting of rTorrent to 1024KB. Check the full list of
57 | available [runtime configs](#runtime-configs).
58 |
59 | If the container starts without errors, visit `http://127.0.0.1` through any web
60 | browser, log in to with the default username/password: `docktorrent/p@ssw0rd`.
61 |
62 | Happy seeding!
63 |
64 | ## Runtime Configs
65 |
66 | There are some environment variables can be supplied at run time:
67 | - **LOGS_OFF**: Set this to `yes` to turn off all logs generated by rTorrent
68 | and other services so that you don't have to worry about space for
69 | `/var/log`. Default is not set.
70 | - **AUTH_OFF**: Disable HTTP authentication on certain network. E.g.,
71 | `192.168.1.0/24` or `all`.
72 |
73 | Override settings in `.rtorrent.rc`:
74 | - **IP** overrides `ip`.
75 | - **MAX_PEERS** overrides `max_peers`.
76 | - **MAX_PEERS_SEED** overrides `max_peers_seed`.
77 | - **MAX_UPLOADS** overrides `max_uploads`.
78 | - **DOWNLOAD_RATE** overrides `download_rate`.
79 | - **UPLOAD_RATE** overrides `upload_rate`.
80 |
81 | ## Requirement
82 |
83 | All you need is to have Docker installed on your system. Check Docker
84 | [Documentation](https://docs.docker.com/installation/) for installation guide on
85 | your OS platform.
86 |
87 | ## Tips
88 |
89 | - `docker stop` can gracefully shutdown rTorrent if you give it more time by
90 | `docker stop -t 120` (which means 120 seconds to time out).
91 |
92 | ## Feedback
93 |
94 | Bug reports and feature suggestions are both welcome. Feel free to use the
95 | [issue tracker](https://github.com/kfei/docktorrent/issues).
96 |
97 | ## Screenshots
98 |
99 | 
100 |
101 | 
102 |
103 | 
104 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:jessie
2 |
3 | MAINTAINER kfei
4 |
5 | ENV VER_LIBTORRENT 0.13.4
6 | ENV VER_RTORRENT 0.9.4
7 |
8 | WORKDIR /usr/local/src
9 |
10 | # This long disgusting instruction saves your image ~130 MB
11 | RUN build_deps="automake build-essential ca-certificates libc-ares-dev libcppunit-dev libtool"; \
12 | build_deps="${build_deps} libssl-dev libxml2-dev libncurses5-dev pkg-config subversion wget"; \
13 | set -x && \
14 | apt-get update && apt-get install -q -y --no-install-recommends ${build_deps} && \
15 | wget http://curl.haxx.se/download/curl-7.39.0.tar.gz && \
16 | tar xzvfp curl-7.39.0.tar.gz && \
17 | cd curl-7.39.0 && \
18 | ./configure --enable-ares --enable-tls-srp --enable-gnu-tls --with-zlib --with-ssl && \
19 | make && \
20 | make install && \
21 | cd .. && \
22 | rm -rf curl-* && \
23 | ldconfig && \
24 | svn --trust-server-cert checkout https://svn.code.sf.net/p/xmlrpc-c/code/stable/ xmlrpc-c && \
25 | cd xmlrpc-c && \
26 | ./configure --enable-libxml2-backend --disable-abyss-server --disable-cgi-server && \
27 | make && \
28 | make install && \
29 | cd .. && \
30 | rm -rf xmlrpc-c && \
31 | ldconfig && \
32 | wget -O libtorrent-$VER_LIBTORRENT.tar.gz https://github.com/rakshasa/libtorrent/archive/$VER_LIBTORRENT.tar.gz && \
33 | tar xzf libtorrent-$VER_LIBTORRENT.tar.gz && \
34 | cd libtorrent-$VER_LIBTORRENT && \
35 | ./autogen.sh && \
36 | ./configure --with-posix-fallocate && \
37 | make && \
38 | make install && \
39 | cd .. && \
40 | rm -rf libtorrent-* && \
41 | ldconfig && \
42 | wget -O rtorrent-$VER_RTORRENT.tar.gz https://github.com/rakshasa/rtorrent/archive/$VER_RTORRENT.tar.gz && \
43 | tar xzf rtorrent-$VER_RTORRENT.tar.gz && \
44 | cd rtorrent-$VER_RTORRENT && \
45 | ./autogen.sh && \
46 | ./configure --with-xmlrpc-c --with-ncurses && \
47 | make && \
48 | make install && \
49 | cd .. && \
50 | rm -rf rtorrent-* && \
51 | ldconfig && \
52 | mkdir -p /usr/share/nginx/html && \
53 | cd /usr/share/nginx/html && \
54 | mkdir rutorrent && \
55 | curl -L -O https://github.com/Novik/ruTorrent/archive/master.tar.gz && \
56 | tar xzvf master.tar.gz -C rutorrent --strip-components 1 && \
57 | rm -rf *.tar.gz && \
58 | apt-get purge -y --auto-remove ${build_deps} && \
59 | apt-get autoremove -y
60 |
61 | # Install required packages
62 | RUN apt-get update && apt-get install -q -y --no-install-recommends \
63 | apache2-utils \
64 | libc-ares2 \
65 | nginx \
66 | php5-cli \
67 | php5-fpm
68 |
69 | # Install packages for ruTorrent plugins
70 | RUN apt-get update && apt-get install -q -y --no-install-recommends \
71 | mediainfo \
72 | unrar-free \
73 | unzip
74 |
75 | # For ffmpeg, which is required by the ruTorrent screenshots plugin
76 | # This increases ~53 MB of the image size, remove it if you really don't need screenshots
77 | RUN echo "deb http://www.deb-multimedia.org jessie main" >> /etc/apt/sources.list && \
78 | apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A401FF99368FA1F98152DE755C808C2B65558117 && \
79 | apt-get update && apt-get install -q -y --no-install-recommends \
80 | deb-multimedia-keyring \
81 | ffmpeg
82 |
83 | # IMPORTANT: Change the default login/password of ruTorrent before build
84 | RUN htpasswd -cb /usr/share/nginx/html/rutorrent/.htpasswd docktorrent p@ssw0rd
85 |
86 | # Copy config files
87 | COPY config/nginx/default /etc/nginx/sites-available/default
88 | COPY config/rtorrent/.rtorrent.rc /root/.rtorrent.rc
89 | COPY config/rutorrent/config.php /usr/share/nginx/html/rutorrent/conf/config.php
90 |
91 | # Add the s6 binaries fs layer
92 | ADD s6-1.1.3.2-musl-static.tar.xz /
93 |
94 | # Service directories and the wrapper script
95 | COPY rootfs /
96 |
97 | # Run the wrapper script first
98 | ENTRYPOINT ["/usr/local/bin/docktorrent"]
99 |
100 | # Declare ports to expose
101 | EXPOSE 80 9527 45566
102 |
103 | # Declare volumes
104 | VOLUME ["/rtorrent", "/var/log"]
105 |
106 | # This should be removed in the latest version of Docker
107 | ENV HOME /root
108 |
--------------------------------------------------------------------------------