ruTorrent: a PHP front end for rTorrent that treats the web server as the real risk
Yet another web front-end for rTorrent
At a glance
- What is it?
- 2,180 stars for an installerless torrent UI. The README now leads with where your profile data must not live, ships an environment checker, and explains what it will not merge.
- Who is it for?
- ruTorrent's recent history is a story about a front end that had spent years treating its own web server configuration as the user's problem. Three consecutive releases concentrated on the same surfaces, the XML-RPC pass-through, the HTTP client, file operations, credential handling and DOM output, and the fix was as much about having one policy read at both entry points as about any individual bug.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
No installer, just a directory that becomes a document root
The deployment model is the first thing to understand, and it has not changed. There is no installation routine and nothing to compile. The sources are unpacked into a directory, and that directory becomes the document root of a web server you already run. Configuration happens afterwards in files under `conf/`.
The feature list is three bullets: lightweight on the server side so it can run on old machines and some home routers, extensible through plugins that anyone can write, and pleasant looking. For a project at 2,180 stars and 425 forks that description is not underselling, because the server-side lightness is what makes the router install real.
The requirements are specific. PHP 7.4 or newer with the `json` and `pcre` extensions, with `simplexml`, `curl`, `mbstring` and `zlib` recommended because some plugins and the XML-RPC proxy need them, plus the `php`, `curl` and `gzip` command line programs. On the BitTorrent side, rTorrent 0.9.8 is the baseline and the 0.16.x series is supported, with other versions explicitly marked as possibly working. That version hedging is worth noting: the UI is tightly coupled to an unusual daemon whose own release history is irregular.
The profile directory is the thing to get right on day one
The README has been rewritten around a single security instruction, and it is the most useful paragraph in the document. Three directories must be kept out of what the web server serves: `share/`, `conf/` and `tests/`. The `share/` directory holds profile data, meaning settings, stored torrents, and the tracker credentials that the `loginmgr` plugin keeps.
That last item is the reason for the emphasis. Tracker credentials sitting inside a document root are one directory traversal or one misconfigured server block away from being readable by anyone. The fix is one line of configuration, pointing the `$profilePath` setting in `conf/config.php` at a directory outside the document root such as `/var/lib/rutorrent`.
The README then splits the remaining defence by server. Apache is already covered, because `.htaccess` files ship inside each of the three directories. nginx and lighttpd do not read `.htaccess` and need the rules from `nginx-example.conf`, which is written for the prefix the install is served under and must be placed before the PHP handler. The honest framing is that one measure has to be right for the others not to matter, which is a better security argument than a list of things to configure.
A bundled checker that talks to rTorrent and refuses to run in a browser
There is a script for verifying an installation, and its design decisions tell you what the project worries about.
php env_check.phpIt checks the PHP version and extensions, the external programs plugins rely on, and common mistakes in `conf/config.php`. It then connects to rTorrent, reports and classifies the daemon version, and checks that ruTorrent's event handlers are registered with it. That last check is the interesting one, because ruTorrent's UI updates through rTorrent events rather than polling, and a misconfigured instance looks like a working interface that never refreshes.
The script exits 0 when everything required passes and 1 otherwise, which makes it usable from a provisioning script or an Ansible check rather than only by reading. And it runs on the command line only, refusing to run under a web server. Given that the same README warns about credential files inside the document root, refusing to expose the diagnostic endpoint is consistent rather than incidental.
Three releases in a month, all of them security work
The recent release history is unusually concentrated. Version 5.3.13, published 2026-09-02, hardened the XML-RPC proxy, made it available as a standalone endpoint, and separated the proxy decision from the send. It also started preserving client-quoted arguments in the `load` command that had previously been dropped, and escaped the download directory inside the `load` command string.
Version 5.3.14, published 2026-09-05, found that the raw XML-RPC pass-through was reading two different copies of one safety list. The standalone endpoint and the httprpc plugin each loaded their own copy of the allowed parameters, and only one of them allowed the download control commands. The consequence was concrete: a client sending stop-all or resume-all as a multicall could be served through one door and refused at the other. The release unifies the policy read at both entry points.
Version 5.3.15, published 2026-09-24, is described as a security hardening release spanning the XML-RPC pass-through, the HTTP client, file operations, credential handling and DOM output, with a denied command refused wherever it is named, spelled, aliased or nested. That phrase, aliased or nested, is the giveaway that these fixes came from adversarial testing rather than from bug reports, since aliases and nesting are techniques you use when probing a filter.
The v5.3.14 release body is also worth flagging as a maintenance signal: its description begins by deferring to a summary the author attributes to an AI assistant, with a note to see the source on GitHub for the details.
Master is the branch, and a release is just a tag
Contributing is documented unusually precisely. Pull requests target `master`, there is no `develop` branch because it was retired, and a release is a tag on `master`. That is a simplification most maintainers would avoid, and it is worth understanding what it means before opening anything: there is no integration branch where changes land first.
The README then states that using AI tooling to write a patch is fine, and that opening what it produced without reading it is not. Three obligations follow, and they are the strictest contribution rules in this batch of projects. Read the entire diff yourself, because a pull request that reformats files it had no reason to touch, or contains changes you cannot explain in your own words, will be closed rather than reviewed. Vouch for it on an installation you actually use, with your own torrents and plugins, left running long enough to watch it behave; a container spun up to prove the diff applies is explicitly not a test, and the pull request must say what it was run against and what was seen. Answer review comments personally, because generated and unread replies stop the conversation there.
The closing rule is scope: whitespace churn, unrelated reformatting and rewritten vendored files make a patch unreviewable, and a patch nobody can review does not get merged. For a project with a `plugins/` directory full of third party code, that last clause is doing real work.
Plugin architecture, and where the license actually is
The tree shows a mature PHP front end rather than a thin page. Alongside `conf/`, `css/`, `js/`, `lang/` and `php/` there is a `plugins/` directory, a `tests/` directory, an `index.html`, an `env_check.php`, an `nginx-example.conf`, an `.editorconfig-checker.json` that suggests formatting is enforced in CI, an `eslint.config.mjs` for the JavaScript, a `phpstan.neon` for static analysis, and both `.vscode/` and `.gitmodules`.
The language metadata reports JavaScript, which understates the PHP that dominates the tree, and the license field reads NOASSERTION, which is GitHub's way of saying it could not classify the license from the files. Both of those are metadata failures rather than project ones. The README states the project is released under GPLv3 and points at `LICENSE.md` in the source, and that file is present at the root of the tree. Anyone vendoring this code should read `LICENSE.md` rather than trusting the repository metadata field.
The two download links are worth distinguishing, because the README is explicit that they answer different questions. The stable version points at the latest tagged release, and the current master link points at a tarball described as what the next release will be cut from. For a front end that talks to a daemon over XML-RPC, testing against master's tarball against a release daemon is a reasonable way to find out whether the two halves of the system are compatible before committing to either.
Editorial conclusion
ruTorrent's recent history is a story about a front end that had spent years treating its own web server configuration as the user's problem. Three consecutive releases concentrated on the same surfaces, the XML-RPC pass-through, the HTTP client, file operations, credential handling and DOM output, and the fix was as much about having one policy read at both entry points as about any individual bug. What that means in practice is that an installation from before this hardening should be treated as needing an upgrade rather than a config review. If you are installing fresh, move the profile directory outside the document root before anything else, run env_check.php from the command line, and remember that the PHP extension list is a requirement for some plugins and the XML-RPC proxy, not an optional extra.
Frequently asked questions
What is ruTorrent?
A web front end for the rTorrent BitTorrent client, written in PHP. There is no installation routine or compilation step: the sources are unpacked into a directory that becomes a web server document root, and configuration happens in files under `conf/`.
How do I update ruTorrent?
The README distinguishes two download links on purpose: the stable version points at the latest tagged release, and a separate current master tarball is described as what the next release will be cut from. Pull requests target master, there is no develop branch, and a release is simply a tag on master, so there is no integration branch to reconcile.
Where should I keep the ruTorrent profile directory?
Outside the web server's document root. The `share/` directory holds settings, stored torrents and tracker credentials kept by the loginmgr plugin, and it sits under the document root by default. Set `$profilePath` in `conf/config.php` to a directory outside the document root, and remember nginx and lighttpd do not read the shipped `.htaccess` files.
Which rTorrent versions does this front end support?
rTorrent 0.9.8 is the stated baseline and the 0.16.x series is supported. The README says other versions may or may not work rather than ruling them out. Running `php env_check.php` from the command line will connect to the daemon, report its version, classify it and check that ruTorrent's event handlers are registered.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/novik-rutorrent)