💾Thananjhayan
← Back to blog

MySeedbox: From a Colab Hack to a Real Self-Hosted Seedbox

July 5, 2026

Last year I turned Google Colab into a free seedbox. It was a fun hack, but it had all the problems you'd expect from running a download server inside a notebook: the runtime died whenever it felt like it, nothing survived a refresh, and the "UI" was a stack of disabled sliders.

So I rebuilt it properly. MySeedbox is a self-hosted seedbox: paste a magnet link into a clean web interface, watch it download in real time, grab the finished files. It runs on any machine that has Docker.

The architecture

Three containers, each doing one job:

  • qBittorrent — the torrent engine. Instead of driving libtorrent by hand like the Colab version did, I let a battle-tested client handle peers, resume data, and queueing, and talk to it through its Web API.
  • FastAPI — a thin backend that wraps the qBittorrent API with the endpoints the frontend actually needs: add a magnet, list downloads with progress, remove a torrent, serve finished files.
  • Vue — the frontend. A single page with an input for magnet links and a live-updating list of downloads — the ipywidgets sliders from the notebook, reborn as actual UI components.

The whole stack starts with one command:

docker compose up -d

What the notebook version taught me

Almost every design decision in MySeedbox is a direct answer to a Colab pain point:

Colab hackMySeedbox
Runtime disconnects kill downloadsqBittorrent runs as a daemon and resumes on restart
No persistence between sessionsState lives in qBittorrent + a mounted volume
Polling loop redraws widget slidersThe frontend polls a proper progress endpoint
Files land in Google DriveFiles land on your own disk, served over HTTP
One notebook, one userA URL anyone on your network can open

Driving qBittorrent from FastAPI

qBittorrent's Web API does the heavy lifting; the backend just translates. Adding a magnet is a single authenticated call, and the progress endpoint maps torrents/info into exactly the JSON shape the Vue app wants — name, progress percentage, download rate, and state. No libtorrent bindings, no state machine of my own, no state_str lookup table.

Why not just expose qBittorrent's own UI?

Fair question — qBittorrent ships with a web UI. Two reasons:

  1. Scope control. The built-in UI exposes every knob a power user could want. I wanted the opposite: one input, one list, zero configuration for whoever I share the URL with.
  2. The fun of it. The point of self-hosting projects like this is learning the full path — API design, Docker networking, a reactive frontend — on a problem small enough to actually finish.

Where it's heading

The code is on GitHub. Next on the list: auth for exposing it beyond the home network, and streaming finished video straight from the seedbox instead of downloading first.

If you ever built the notebook version — this is what it wanted to be when it grew up.

💬 Comments