A unified self-hosted web interface for managing downloads across aMule (ED2K/Kademlia), Transmission (torrents) and pyLoad NG (direct downloads) — all from a single dashboard, deployed with Docker Compose.
- Unified downloads view — aMule files, torrents and pyLoad packages in one table (or mobile card layout on small screens)
- aMule — browse/search the ED2K network, manage downloads, view chunk availability, sources, friends, servers, KAD status and preferences
- Transmission — add torrents via magnet/URL, control downloads, inspect peers/trackers/files, manage network and speed settings
- pyLoad NG — add direct-download packages, monitor link status, stop/restart/delete packages
- Torrent search — search torrent indexes from within the UI (extensible via plugins)
- Plugin system — upload
.jsplugins to add media providers (movies, shows, …) or torrent-search indexes without restarting the server - Statistics — live aMule stats tree and Transmission session stats
- Multi-user auth — JWT-based login, per-user preferences
- Theming — light / dark mode
- i18n — English, Spanish, Italian
- Mobile-friendly — responsive layout with card view on small screens
Browser
│
└─ transmule-app (port 3001)
│ nginx — serves Nuxt SPA
│ — proxies /api/* and /_scalar → 127.0.0.1:3000
│
└─ Nitro API (127.0.0.1:3000, loopback only)
├─ JWT auth + user management (SQLite)
├─ CORS handling
├─► aMule EC protocol (internal :4712)
├─► Transmission RPC (internal :9091)
└─► pyLoad NG API (internal :8000)
The frontend SPA and the Nitro API share a single container managed by supervisord. nginx handles static file serving and proxies API traffic to Nitro on the loopback interface — no IP address is ever baked into the image.
git clone git@github.com:Jo3l/transmule.git
cd transmule
cp .env.example .envEdit .env — at minimum set your passwords and file paths:
AMULE_GUI_PASSWORD=your_amule_password
JWT_SECRET=a-long-random-string
PYLOAD_USER=pyload
PYLOAD_PASSWORD=pyloaddocker compose up -d- Frontend / API: http://localhost:3001
- Swagger docs: http://localhost:3001/_scalar
On first run you will be prompted to create an admin account.
| Port | Service | Note |
|---|---|---|
3001 |
App (nginx + Nitro) | UI + proxied API + Swagger (/_scalar) |
16881 (TCP) |
aMule ED2K | Configurable via AMULE_ED2K_TCP_PORT |
16882 (UDP) |
aMule ED2K | Configurable via AMULE_ED2K_UDP_PORT |
16883 (UDP) |
aMule Kademlia | Configurable via AMULE_KAD_UDP_PORT |
16884 |
Transmission peers | Configurable via TRANSMISSION_PEER_PORT |
All service-to-service communication (aMule EC, Transmission RPC, pyLoad API) happens on the internal Docker network and is not exposed to the host. Nitro listens on 127.0.0.1:3000 inside the app container and is not exposed externally.
| Variable | Default | Description |
|---|---|---|
PUID / PGID |
1000 |
Host user/group IDs for file permissions |
TZ |
Europe/Madrid |
Timezone |
DOWNLOAD_DIR |
./downloads |
Completed downloads host path |
INCOMPLETE_DIR |
./incomplete |
In-progress downloads host path |
AMULE_GUI_PASSWORD |
— | aMule EC protocol password (port 4712) |
TRANSMISSION_USER / TRANSMISSION_PASS |
(empty) | Transmission RPC credentials |
DATA_DIR |
./data |
Middleware SQLite database directory |
JWT_SECRET |
change-me |
Secret for signing JWT tokens |
PYLOAD_USER / PYLOAD_PASSWORD |
pyload |
pyLoad NG credentials |
Requirements: Node.js 20+, Docker (for the back-end services).
# Start back-end services only (aMule, Transmission, pyLoad)
docker compose -f docker-compose.dev.yml up -d
# Middleware (hot-reload)
cd middleware && npm install && npm run dev
# Frontend (hot-reload)
cd frontend && npm install && npm run devOr use the convenience script at the root:
./dev.sh| Layer | Technology |
|---|---|
| Frontend | Nuxt 3 + Vue 3, custom SCSS |
| Middleware | Nitro (Node.js) |
| Database | SQLite via better-sqlite3 |
| Auth | JWT (jose) |
| aMule client | EC binary protocol (custom implementation) |
| Transmission client | Transmission RPC JSON API |
| pyLoad client | pyLoad NG HTTP API |
| Containers | Docker Compose — ngosang/amule, linuxserver/transmission, linuxserver/pyload-ng + combined app image (nginx + Nitro via supervisord) |
TransMule supports a runtime plugin system for extending media providers and torrent-search indexes.
Official plugins are maintained in the transmule-plugins repository.
Two plugin types are supported:
| Type | What it does | Key method |
|---|---|---|
Media (mediaType) |
Adds a sidebar browse/search section for a content type (movies, shows, …) | list(params) |
Torrent Search (pluginType: "torrent-search") |
Powers the Transmission → Torrent Search page with a new index source | search(query, limit, extraTrackers) |
- Open TransMule → Settings → Providers
- Click Upload Plugin and select a
.jsfile - Reload the page — the plugin is active immediately
No server restart needed. To remove a plugin, click Remove next to it in the Providers panel.
| Plugin | Type | Description |
|---|---|---|
dontorrent-movies |
movies | Spanish movie torrents from dontorrent.link |
dontorrent-shows |
shows | Spanish series torrents from dontorrent.link |
yts |
movies | Movie browse/search via YTS.mx with quality & genre filters |
showrss |
shows | TV show torrents from your personal ShowRSS RSS feed |
nyaa |
torrent-search | Anime & manga torrents via nyaa.si RSS |
piratebay |
torrent-search | General torrents via apibay.org JSON API |
yts-search |
torrent-search | Movie torrents via YTS.mx JSON API |
Download them from github.com/Jo3l/transmule-plugins.
