Docker linuxserver/rutorrent deprecated, what I have done!

The LinuxServer team has deprecated their image linuxserver/rtorrent/rutorrent due to a lack of maintainers! I will explain in this article what I have done to replace this image.

Docker linuxserver/rutorrent deprecated, what I have done!

The LinuxServer team has deprecated their image linuxserver/rtorrent/rutorrent due to a lack of maintainers!
They now suggest to use crazymax/rtorrent-rutorrent instead. I have decided to give it a try and finally after few tests and adaptations, I have migrated for good!

I will detail below all customization I have made to keep the same experience and usage I had with the previous one.

ℹ️ It's important to mention that most of the changes introduced on this image has been made, by the author, to avoid to use rutorrent plugins at the maximum.

More details below! 😉

Please note that this image can be even more customized if you build it yourself

Download folders

Linuxserver is using:

  • A temp folder  /downloads/incoming
  • A finished folder /downloads/completed
  • A watch folder /downloads/watch available to be used with Autotools>AutoWatch

Crazy-max is using:

  • A temp folder /downloads/temp
  • A finished folder /downloads/complete ⚠️Note the slight difference here
  • A watch folder /data/rtorrent/watch which is the default rtorrent folder (Remember the note about getting rid of rutorrent plugins?)
  • I have anyway created /data/watched to keep using Autotools>AutoWatch easily

Configuration

Environment file and port management

A lot of settings can be configured from the environment file, please find below mine and some explanations

  • The property RU_REMOVE_CORE_PLUGINS gives you the ability to remove completely some rutorrent plugins when you create your container (Remember the note about... ok you got it!). Be careful, some components have cross-dependencies! For example, Autotools requires data to work properly.
  • At the end of the file, you can see 5 properties to customized all the ports. It's a feature I have requested, thanks for the super-fast implementation.  This is a must have if you want to use more than one container behind VPN and avoid conflicts
  • I also customized MEMORY_LIMIT and UPLOAD_MAX_SIZE for container with huge volumes of data
  • Find out more on GitHub
TZ=Europe/Paris
PUID=1026
PGID=100

MEMORY_LIMIT=1024M
UPLOAD_MAX_SIZE=32M
OPCACHE_MEM_SIZE=256
MAX_FILE_UPLOADS=10
REAL_IP_FROM=0.0.0.0/32
REAL_IP_HEADER=X-Forwarded-For
LOG_IP_VAR=remote_addr

XMLRPC_AUTHBASIC_STRING=rTorrent XMLRPC restricted access
RUTORRENT_AUTHBASIC_STRING=ruTorrent restricted access
WEBDAV_AUTHBASIC_STRING=WebDAV restricted access

RT_LOG_LEVEL=info
RT_LOG_EXECUTE=false
RT_LOG_XMLRPC=false

RU_REMOVE_CORE_PLUGINS=httprpc,_cloudflare,_noty,_noty2,cookies,extratio,extsearch,feeds,filedrop,history,loginmgr,lookat,retrackers,rss,rssurlrewrite,rutracker_check,scheduler,screenshots,show_peers_like_wtorrent,spectrogram,trafic,unpack,uploadeta,xmpp
RU_HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 6.0; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
RU_HTTP_TIME_OUT=30
RU_HTTP_USE_GZIP=true
RU_RPC_TIME_OUT=5
RU_LOG_RPC_CALLS=false
RU_LOG_RPC_FAULTS=true
RU_PHP_USE_GZIP=false
RU_PHP_GZIP_LEVEL=2
RU_SCHEDULE_RAND=10
RU_LOG_FILE=/data/rutorrent/rutorrent.log
RU_DO_DIAGNOSTIC=true
RU_SAVE_UPLOADED_TORRENTS=true
RU_OVERWRITE_UPLOADED_TORRENTS=false
RU_FORBID_USER_SETTINGS=false
RU_LOCALE=UTF8

RT_DHT_PORT=6840
XMLRPC_PORT=8040
RUTORRENT_PORT=33440
WEBDAV_PORT=9040
RT_INC_PORT=50040
My environement file

.rtorrent.rc customization

The .rtorrent.rc configuration file (/data/rtorrent/.rtorrent.rc) contains by default few customization worth to mention.

First of all, these 2 lines:

# Watch a directory for new torrents, and stop those that have been deleted
schedule2 = watch_directory, 1, 1, (cat,"load.start=",(cfg.watch),"*.torrent")
schedule2 = untied_directory, 5, 5, (cat,"stop_untied=",(cfg.watch),"*.torrent")


They activate the usage of the rtorrent watch folder (/data/rtorrent/watch) to import the torrent and label them (if inside a folder) to get rid of Autotools>Autowatch and Autotools>Autolabel. I have commented these 2 lines as rtorrent watch feature is not recursive above one folder so I will keep using Autotools.
In addition, it creates also a binding between the torrent file in the watch folder (which is not delete when imported) and its session. Remove one removes the other one and I didn't want to use it that way.

Then there is 3 lines to avoid using Autotools>Automove. I have commented it as well to keep using Autotools.

# Move finished (no need Autotools/Automove plugin on ruTorrent)
method.insert = d.get_finished_dir, simple, "cat=$cfg.download_complete=,$d.custom1="
method.insert = d.move_to_complete, simple, "d.directory.set=$argument.1=; execute=mkdir,-p,$argument.1=; execute=mv,-u,$argument.0=,$argument.1=; d.save_full_session="
method.set_key = event.download.finished,move_complete,"d.move_to_complete=$d.data_path=,$d.get_finished_dir="
directory.default.set = (cat,(cfg.download_complete))

And last but not least!

# Erase data when torrent deleted (no need erasedata plugin on ruTorrent)
method.set_key = event.download.erased,delete_erased,"execute=rm,-rf,--,$d.data_path="

⚠️This is a warning sign to catch your attention as its a topic worth to mention!
This configuration is setup to automatically delete all data files associated with a torrent when using the function "Remove" in the interface which normally only remove the torrent and not the data.
To remove the torrent and the data, you will normally have to use Remove and Delete data in the interface, which is provided by the plugin erasedata. The author of the image put this configuration line by default to avoid having to use erasedata plugin, nevertheless I do not agree with that and I find the ability to remove a torrent without touching its data pretty useful so I also commented this line.

Using Delete to remove the torrent but not the data is useful for torrent which do not verify at 100% for example (missing a file or whatever)

Migrating torrents and session

After few tests, I was not able to migrate "easily" my session folder between the 2 images. I tried to:

  • Copy the session folder content from one image to the other
  • Run a search and replace /downloads/completed to /downloads/complete
  • Start the container

It never worked as expected! As you know me well, I never would have accepted to migrate manually one by one so I did a python script to ease this by:

  • Find all torrents in the watch folder (Do a copy before!)
  • Read the associated session files
  • Extract the path after /downloads/completed
  • Rebuild a tree of folders and move .torrent inside so you can just move it in your watch folder and let the magic happens! ✨

You will have to run through the content checking for all of them but at least, no manual operations.

import re
import sys,os
import shutil
import urlparse

try:
    os.makedirs("_done")
except OSError:
    if not os.path.isdir("_done"):
        raise

files = [f for f in os.listdir('.') if os.path.isfile(f)]

for f in files:
    if f.endswith('.torrent'):

        print("Filename:" + f)
        sessionFilename = f +".rtorrent"
        libFilename = f +".libtorrent_resume"

        print("-- Session:" + sessionFilename)
        print("-- Libresume:" + libFilename)

        # Reading session file to get the current path
        with open (sessionFilename, 'rt') as sessionFile:
            sessionContent = sessionFile.read()

        # Extract path with regex
        results=re.search(r'(?<=:\/downloads\/complete\/)(.*?)(?=7:hashing)', sessionContent)
        if results is not None:
            pathRaw=results.group(1)
            print("-- pathRaw:" + pathRaw)
        else:
            pathRaw=None

        if pathRaw:
            # Remove the base path
            pathCleaned=pathRaw.replace("/downloads/completed/", "")

            # Remove trailing slash
            pathTarget=re.sub('/[^/]+$', '/', pathCleaned)

            print("-- Path:" + pathCleaned)
            print("-- Target:" + pathTarget)
            print("-----------------------")

            # Create the path

            try:
                os.makedirs(pathTarget)
            except OSError:
                if not os.path.isdir(pathTarget):
                    raise

            # Move the files
            path = os.path.join(pathTarget, f)
            shutil.move(f, path)
            shutil.move(sessionFilename, "_done")
            shutil.move(libFilename, "_done")


When all of this was done, I had a tought 💡
The session incompatibility might be due to the removal of some plugins in the new image, you should try without first and let me know 😉

Others features!

This image contains somes interesting features like the theme importing which let you import new one by just adding a folder into /data/rutorrent/themes. The same works for plugins into /data/rutorrent/plugins.

You can also overload an existing configuration by adding files into /data/rutorrent/plugins-conf. You can find an example below to active debug and increase the interval of Autotools plugin.

<?php

    // set interval for schedule command in seconds
    $autowatch_interval = 60;

    // set "true" to enable debug output
    $autodebug_enabled = true;
/data/rutorrent/plugins-conf/autotools.php

The image also include a pretty straight forward way to manage the htaccess authentication, more information into the official documentation.

Conclusion

I didn't want to keep a deprecetad image and I've been seduced by this one and all its customization like the themes or plugins importer/overloader.
The easy port customization is awesome!

I hope it helped! Stay tuned!

Looking for help?
If you are looking for some help or want a quick chat, please head over to the Discord Community!