nefarious: a self-hosted front end that automates torrent acquisition
Web application for automatically downloading TV & Movies (w/ VPN)
At a glance
- What is it?
- nefarious is a Django and Angular web application that puts a browser UI in front of Jackett and Transmission, so searching, filtering, queueing, and monitoring media downloads happens in one place instead of in a torrent client. It ships as a multi-container Docker Compose stack with Celery, Redis, and an auto-updating watchtower service.
- Who is it for?
- Adopt nefarious if you already run Jackett and Transmission and want a single web interface for search, filtering, and status, including from a phone. Do not adopt it if you have never run a torrent stack, since the value is in the orchestration layer rather than the downloading.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The web layer over two existing tools
nefarious is a web application that automatically downloads movies and TV shows, and the architecture is best understood as a front end over two things you could already be running.
Jackett searches for torrents and Transmission handles the downloading, and the README says exactly that, in that order. Everything nefarious adds is the layer in between: a browser interface where you search, browse results by popularity, genre, or year, apply filters, decide what should be downloaded automatically, and watch the progress.
That framing explains the feature list. Search and discover by popularity, genres and year is a browsing experience built on metadata rather than a raw search box. Auto download is the queueing decision. Find similar and recommended titles via The Movie Database and Rotten Tomatoes is the metadata layer, and the trailers, the internationalised titles, descriptions and poster artwork, and the multiple language support all come from the same place. The TMDB and Rotten Tomatoes integrations are what make the app feel like a media library rather than a search box, and they are also the reason it can offer a Wanted and Watching view.
The primary language is Python with an Angular front end, the project is GPL-3.0 licensed, the homepage is lardbit.github.io/nefarious, and the last push to the repository was on 2026-10-15. There are no GitHub releases, so the container image on Docker Hub is the artefact you actually consume.
The filter stack, and the two blacklists
The filtering features are where an automation tool either earns its place or becomes a nuisance, and nefarious has a substantial set of them.
Quality profiles are the first. You can specify that only 1080p movies and only 720p TV should be downloaded, which is a rule applied to the results before anything is queued. User defined keyword filters do the opposite work, letting you ignore things like x265 or hevc codecs, and there is a separate setting for whether to download media with hardcoded subtitles or not. There is also a control for whether the results should be searched manually rather than automatically.
Two blacklists sit on top of that. The first is manual, and it permanently avoids a bad or fake torrent that you have identified yourself. The second is automatic, and it is the more interesting one, since it autodetects and blacklists spam or fake video content, and it also autodetects and blacklists stuck torrents that fail to complete after a certain number of days. The second of those solves a real operational problem, because a torrent that never completes occupies a slot in the client indefinitely.
The rest of the feature set is operational. Transmission results and status are monitored from within the app rather than from the client. Media is automatically renamed on arrival. Existing libraries can be imported. Subtitles are fetched automatically through the opensubtitles API. Notifications go out through Apprise, which is the service that lets one configuration reach all the major notification providers, and the README pins that integration to a specific Apprise version.
There is also a self-updating application feature, and multi-user support with permission groups, so admin users and regular users see and do different things.
The compose stack: five services and three volumes
The docker-compose.yml file is the clearest description of the system, and it opens with a warning banner that says DO NOT EDIT THIS FILE, with the instruction to create an .env file instead.
The services are defined in docker-compose.base.yml and extended into the main file. The nefarious service is the main application and depends on redis, jackett, and celery. The celery service is the background task queue and depends on redis. There is a celery-scheduler service for the background task queue scheduler, also depending on redis. The redis service is the database for the task queue, with a restart policy of always and a memory limit of 200m, and it exposes 6379 rather than publishing it. The jackett service is the torrent indexer and publishes 9117. The transmission service is the torrent server, using the linuxserver/transmission image. The watchtower service is the auto update service.
The named volumes are nefarious-db, jackett-config, and transmission-db, and the presence of those three is what makes the upgrade path safe, since the settings live in the volumes rather than in the containers.
There are three compose files in the repository besides the main one: docker-compose.base.yml, docker-compose.dev.yml, and docker-compose.transmission-vpn.yml, the last being the optional VPN integration. The entrypoint scripts mirror the same split, with entrypoint-base.sh, entrypoint-celery.sh, and entrypoint.sh.
The application image itself is built from python:3.13-bookworm, adds the src directory as the application, and copies the built Angular assets in from a separate frontend image stage. The build installs the ffmpeg and HDF5 development libraries, creates a virtualenv, installs pip 24, installs the requirements, and runs collectstatic. The compose file expects the frontend to be built separately, which is what the Dockerfile-frontend file is for.
Setup, and the two URLs you have to get right
You need Docker and docker-compose installed already, and the setup is four commands. Clone the repository, copy the environment template, edit it, and start the containers:
git clone https://github.com/lardbit/nefarious.git
cd nefarious
cp env.template .env
docker-compose up -dThe one setting you must define is HOST_DOWNLOAD_PATH, set to something like HOST_DOWNLOAD_PATH=/path/to/downloads, which is how the containers find the place on the host where the finished media should land. The README is emphatic that you should never need to edit the docker-compose.yml file, since all settings are read from .env.
The first start can take a few minutes, because the images have to be pulled and the database has to be prepared. After that three local URLs are listed: nefarious at http://localhost:8000, Jackett at http://localhost:9117, and Transmission at http://localhost:9091.
The configuration step in Part 2 is the one that catches people. The default user and password are admin and admin, and on first login you are directed to the main settings and asked to configure your Jackett API token. Jackett's host should remain jackett and the port should remain 9117, and the API token is copied from the Jackett interface at http://localhost:9117. Transmission's host should remain transmission and the port should remain 9091, with the username and password left blank by default, and the documentation is specific that setting them in nefarious should only be done if the Transmission settings were also configured on the Transmission side.
One more thing has to be done in Jackett itself, and it is not optional: you have to add indexers to track your preferred content, and be sure to test them to see that they are working. The examples named are The Pirate Bay, 1337x, and RARBG. Until that is done, nefarious has nothing to search.
The VPN path, and the low powered path
Two optional configurations are documented as separate documents, and both address a real constraint rather than a feature wishlist.
The VPN integration is optional and lives in its own compose file, docker-compose.transmission-vpn.yml, with the details in docs/VPN.md. The interesting part is where the VPN sits. Because the network requirement is that the download traffic should leave through a tunnel rather than from the home connection, and because Jackett performs the searching, the natural arrangement is that the searching happens locally while the downloading happens through the tunnel. Splitting those two means the search indexers see requests from the same address as the client would, which avoids the situation where an indexer blocks the address because it was sending traffic from a datacenter.
The low powered configuration is documented in docs/SBC.md and covers single board computers such as the Raspberry Pi, ODROID, and Pine. This is a direct answer to the fact that running a full media stack on a small single board computer is constrained by memory and CPU, and the download server is the component that needs the most of both. The compose file reflects that attention to resources, with the Redis service explicitly capped at 200 megabytes and the transmission service using the linuxserver image.
The other documented files follow the same pattern of pushing detail out of the README: docs/DEPENDENCIES.md for the dependency list, docs/USAGE.md for day to day use, docs/TROUBLESHOOTING.md, and docs/DEVELOPMENT.md.
Upgrading, and the one thing that breaks it
The upgrade story is unusually clean, and it comes down to the persistent volumes.
If you are running nefarious via the default docker-compose.yml file, nefarious will automatically update to the newest versions as they release, which is the watchtower service doing its job. However, the documentation points out that occasionally the docker-compose.yml configuration file changes and you will need to redo the steps in the setup section. The reassurance is that you will not lose your nefarious settings because of persistent Docker volumes, and it describes the operation as safe.
The manual trigger for a configuration change is the force-recreate flag, and the README gives the exact command for the case where you have edited the Transmission settings file:
docker-compose up -d --force-recreate transmissionThat detail is worth understanding, because it explains a class of confusing behaviour. The transmission-settings.json file is mounted into the container, but Transmission reads its configuration once at startup, so editing the file on the host changes nothing until the container is recreated. The same applies to any other service with a file-based configuration.
The project also carries an AGENTS.md and a mise.toml at the top level, a _config.yml, and a ty.toml for the ty type checker, which suggests the repository is set up for automated tooling rather than a bare Python checkout.
Editorial conclusion
Adopt nefarious if you already run Jackett and Transmission and want a single web interface for search, filtering, and status, including from a phone. Do not adopt it if you have never run a torrent stack, since the value is in the orchestration layer rather than the downloading. Verify first that the indexers you intend to use are configured in Jackett, because nefarious delegates all searching to it and cannot find anything on its own.
Frequently asked questions
What does nefarious do that Jackett and Transmission do not?
nefarious is the web layer between them. Jackett searches for torrents and Transmission handles the downloading, while nefarious provides the browser interface for searching, discovering by popularity, genre and year, applying quality profiles and keyword filters, queueing automatically, and monitoring status.
How do I install nefarious?
You need Docker and docker-compose. Clone the repository, run cp env.template .env, set HOST_DOWNLOAD_PATH in the .env file to where downloads should land on the host, and start the stack with docker-compose up -d. The first start can take a few minutes, and the app is then at http://localhost:8000.
What are the default ports and the default credentials?
nefarious is on port 8000, Jackett on 9117, and Transmission on 9091. The default nefarious user and password are admin and admin, and on first login you are asked to configure the Jackett API token, with Jackett's host left as jackett and Transmission's as transmission.
Why does nefarious find nothing after I install it?
Because searching is delegated to Jackett, and Jackett has no indexers configured by default. The documentation says to add indexers in Jackett to track your preferred content and to test them to make sure they are working before expecting results in nefarious.
What happens to my settings when nefarious updates itself?
Nothing, because the settings live in persistent Docker volumes, specifically nefarious-db, jackett-config, and transmission-db. The one manual step is that if the docker-compose.yml file itself changes you need to redo the setup steps, and if you edit transmission-settings.json you have to run docker-compose up -d --force-recreate transmission for the change to take effect.
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/lardbit-nefarious)Was this useful?