rtorrent + rutorrent & nginx on Ubuntu 18.04

Recently I acquired a Dell PowerEdge R610 for one purpose, and decided to virtualize all the things! This posed an issue when I went googling for information on typical configurations; typically a headless VM doing this task is a seedbox and so many things were geared toward that usage. But I didn’t need things like an ftp server or something to just grab and hoard everything.

So I dove in, broke a lot of stuff, fixed some, and ripped out broken parts I didn’t need. I figured I’d share my experiences; as well as some of the hassles I had from my particular setup.

For this setup I provisioned a quad vCPU machine with 2 gigs of ram, a 10gig hdd image, and two network interfaces. The machine I originally was using for this task was a dual CPU with 4 gigs of ram; but that machine also ran a full desktop in addition to things like apache and hostapd. The amount of ram is a starting point; if I need to increase it I can just shut the VM down for the amount of time it takes to add ram and boot it back up. In addition; the vCPUs are configured as quad socket and I only activated two. I can add the additional ones as needed without rebooting.

The Storage Tangent

“Why did you give a torrent machine a 10 gig HD?”

So here’s the screwy thing about my storage situation; for the last few years, I’ve stored all of my torrents on a NAS appliance…a Seagate PersonalCloud. While this did choke the network switch; it basically meant that all my data was just getting dumped on to something I could SMB directly in to. This way…the amount of local storage didn’t matter for torrents, but it meant if I ever upgraded/changed machines I only had to point to that directory to restore everything.

Now plugging the PersonalCloud in to one of the 610’s empty network ports, assigning it to a VM, and then pulling from it over CIFS on the dedicated link might have worked; but SMB sucks for lots of small files. I won’t talk about why I originally hacked Debian on to the Seagate appliance for a failed project; the point is the thing now runs some custom firmware based on a custom build of Linux. (Turns out the hard drive was bad, and now I’ve got some Synology thing I’m actually waiting for Amazon to deliver.)

So…instead what I do, taking some advice from the department of redundancy department; is have a VM performing some NAS functions that’s visible to my LAN for SMB/Windows/CIFS. It has a NFS share from the Seagate mounted on it’s file-system; which serves as the basis for Samba shares. To make it even more complicated; the NAS VM reshares the NFS mount as an NFS share to an internal network in Xen so they too can access the remote storage’s remote storage.

So that’s why I have just a 10gig disk on my VM. Through some crazy double act of double NAS and hacking around permissions hell; they’re all stored remotely. It’s also why I don’t need anything to “assist” me in getting data off my “seedbox”.

Setting Up The Requirements

In order to get this going, you’ll need to install or have the following on your machine:

sudo apt install nginx php-fpm rtorrent curl python git 

Now we need to do some configuration of nginx for both php and rutorrent.

sudo nano /etc/nginx/sites-available/default

It’s probably a good idea to make a backup of this file in case you need to start over. I didn’t care as I’d just nuke the VM and start from scratch. This probably isn’t the most secure method either; but the only process visible to the outside world is rtorrent.

Configure nginx

So the basic configuration changes we’re making are to setup PHP and the SCGI information rutorrent will need. Look for this line and add index.php:

# Add index.php to the list if you are using PHP
        index index.php index.html index.htm index.nginx-debian.html;

The following lines you can add to the bottom of the file.

location /RPC2 {
  include scgi_params;
  scgi_pass localhost:5000;
}

 location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }

If you already have something on port 5000 or need/want to use another one; you just need to remember what you use for rtorrent configuration. In these examples, I will just simply use 5000. If you are running something other than php7.2 (or on something other than Ubuntu), make sure the socket information matches your install.

sudo systemctl restart nginx

Restart nginx however your system is setup to activate the changes. You can drop a php test file in your html directory to verify that PHP is working.

Configure rtorrent

The next step is configuring rtorrent; which was not that complicated once I found a good file to work from. In fact this next block of code comes from the rtorrent wiki; downloading the example template, saving it as the config file, and making the session directory.

curl -Ls "https://raw.githubusercontent.com/wiki/rakshasa/rtorrent/CONFIG-Template.md" \
    | sed -ne "/^######/,/^### END/p" \
    | sed -re "s:/home/USERNAME:$HOME:" >~/.rtorrent.rc
mkdir -p ~/rtorrent/

For obvious reasons we now need to look through and modify the rtorrent.rc file.

nano .rctorrent.rc

I’ll start with the things we absolutely have to modify; and the first is the scgi configuration. The port has to match the one you set up in nginx.

network.scgi.open_port = 127.0.0.1:5000
network.http.ssl_verify_peer.set=0

You may also want to examine and/or modify the default paths:

## Instance layout (base paths)
method.insert = cfg.basedir,  private|const|string, (cat,"/home/dewdude/rtorrent/")
method.insert = cfg.download, private|const|string, (cat,"/media/remote/torrents/")
method.insert = cfg.logs,     private|const|string, (cat,(cfg.basedir),"log/")
method.insert = cfg.logfile,  private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log")
method.insert = cfg.session,  private|const|string, (cat,(cfg.basedir),".session/")
method.insert = cfg.watch,    private|const|string, (cat,(cfg.basedir),"watch/")

In my case I didn’t have any concern other than the default download directory. It’s worth noting you should delete any references to “cfg.directory” when using a full path and not a one relative from the cfg. assignment. Or just be lazy and symlink something over…what do I look like, the Linux Police?

Start up rtorrent and if it doesn’t error out; you’re good. If you do get errors, make sure the directories actually exist and are writable. Ctrl+Q will back you out of rtorrent.

Install & Configure rutorrent

Remember how I said security was going to be low? Well we’re going to continue this trend by making life easier and just making our www directory writable by everyone.

sudo chmod 777 /var/www/html

Now browse to /var/www/html (or whatever your www directory is) and simply git rutorrent. Provided you didn’t screw up the permissions, you won’t have to sudo this.

git clone https://github.com/Novik/ruTorrent.git

There are some permissions to take care of:

chmod -R 777 share/
cd conf
nano config.php

Among the many things we need to do in the rutorrent config is add the scgi information we used for nginx and rtorrent.

$scgi_port = 5000;
$scgi_host = "127.0.0.1";

rutorrent and some of it’s plugins rely on external applications. It’s supposed to pull these from the path variable; but it doesn’t appear to work. So we’ll need to add information to the $pathtoExternals array:

 $pathToExternals = array(
                "php"   => '/usr/bin/php',                      
                "curl"  => '/usr/bin/curl',                     
                "gzip"  => '/usr/bin/gzip',                     
                "id"    => '/usr/bin/id',                       
                "stat"  => '/usr/bin/stat',                     
                "pgrep" => '/usr/bin/pgrep',                    
                "python" => '/usr/bin/python3.6',                 
        );

These were all the settings used on my system and the only one that might be different is your python binary. In any case, you can use “whereis” to figure what the full path is:

dewdude@seedbox:~$ whereis python
python: /usr/bin/python3.6 /usr/bin/python3.6m /usr/lib/python3.6 /usr/lib/python3.8 /usr/lib/python2.7 /usr/lib/python3.7 /etc/python3.6 /usr/local/lib/python3.6

After you save the file you can start up rtorrent and then load up rutorrent in your browser at http://sever.ip/rutorrent.

Ripping Off The Broken Bits

The process of specifying paths in the config.php came about due to several errors I got the first time I loaded rutorrent up. By default the repository includes a large number of plugins; many of which I probably won’t even use. I still wanted to give them “a chance” and to provide some instructions that went as far as I could with total default sources. In fact; rutorrent will tell you which process the webserver cannot access. All you need to do is install that component and add a line for it under $pathtoExternals.

However, the plugins I had left were ones I could tell by just name I had no use for. The process to uninstall a plugin is simply deleting it’s directory from /rutorrent/plugins/

rm -r _cloudflare
rm -r mediainfo
rm -r spectrogram
rm -r unpack

Any remaining configuration you can do from ruTorrent’s interface much like you would something like qBittorrent.

I originally forgot to add the process for making this a service, so it automatically starts if your stuff ever reboots; you can read that over here.