Mediocre Blog by mediocregopher    //    Follow  /  RSS  /  License

Running ruTorrent With Nix

- I've said it before and I'll say it again: docker is for boomers.


For the last year or so I've been slowly transitioning all services on my home server from using docker to using nix. As of today the process is finally complete, and I've disabled the docker service entirely.

The last piece of this process was my ruTorrent instance, which I use to manage torrents on my home server from within my LAN. ruTorrent is actually just the php application which sits on the frontend, so to get this set up fully you also need a FastCGI+HTTP server to host it, and an rTorrent instance to act as the actual torrent client. The docker image I had been using previously had dealt with all of this, but now I've had to do it manually.

The final result is rutorrent.nix, which you can check out if you want to follow along. When built it produces a single binary, which contains all configuration and other runtime dependencies which are required to run it. The only thing the user needs to worry about is running it as a daemon on their OS of choice.


For FastCGI+HTTP I'm using lighttpd, which by its name you could guess is fairly lightweight and simple to set up. It has all the necessary modules to run a php application already built in, and its configuration language is odd but simple.

I'm running rTorrent and lighttpd together in the pmux process manager, so that they can be treated as a single process for most intents and purposes. There's also some auxillary processes set up to run tail -f on various log files which rTorrent and lighttpd otherwise refuse to print to stdout.

lighttpd is configured to expose a single HTTP unix socket at a pre-configured path. The intention is that some other HTTP reverse proxy (I recommend Caddy) deals with details like virtual hosts, access control, and TLS. Only the actual serving of the application is left to the socket. Here's my Caddy vhost configuration, for reference:

rutorrent.hostname.localnet {

    import private // only allows certain ip ranges

    reverse_proxy unix//run/rutorrent/http.sock

    basicauth {
        username password-hash
    }
}

All processes are expected to run as a non-root user. Ideally ruTorrent would run as its own rutorrent system user, but it's not a hard requirement. Since the lighttpd processes exposes the HTTP unix socket as this user, it's important to ensure that whatever reverse proxy you're using has permissions to access this socket file. This can be made easier using ACLs.


The final component of my ruTorrent setup is a VPN wrapper. There's many unsavory characters roaming the public internet, looking to harass torrent users in various ways (some not altogether legal). The goal is that none of the processes related to ruTorrent are ever able to communicate directly with the public internet, but must route all connections over a VPN, which offers some level anonymity and protection.

I was previously accomplishing this by sharing the network from a container running OpenVPN with the one running ruTorrent (see this post for an example). Obviously this is no longer an option, as docker is out of the equation.

My solution is to use vopono, which sets up a linux network namespace which only has access to a VPN interface. The configuration of vopono is very specific to which VPN service one uses, so I won't bother showing mine here. But it does work quite well, and can be tested by simply running /bin/bash under vopono, and trying various curl commands.

Hopefully this is helpful for anyone trying to set up a torrent service on their server which is running nix. Quite a broad audience, to be sure!

Published 2022-08-10
Last updated 2022-08-13


This post is part of a series.
Previously: Another Small Step For Maddy