Private tracker passkey protector for qBittorrent.
Vault-Tracker is a lightweight Docker service that automatically protects your private tracker passkeys during the download phase. It strips tracker URLs (and their embedded passkeys) from new private torrents as soon as they are added, stores them safely in a local database, and reinjects them once the torrent is ready to seed — keeping your ratio intact and your credentials unexposed.
When you add a torrent from a private tracker, the .torrent file contains tracker URLs with your unique passkey embedded in them. During the download phase, your client announces to those trackers — consuming ratio and exposing your passkey to every peer.
Vault-Tracker solves this by:
- Immediately stripping private tracker URLs from new torrents (zero ratio consumed during download).
- Safely storing the tracker URLs + passkeys in an encrypted-at-rest SQLite database.
- Automatically reinjecting them when the torrent transitions to seeding — so you seed normally without manual intervention.
┌─────────────────────┐
│ qBittorrent WebUI │
│ (existing server) │
└──────────┬──────────┘
│ API v2
▼
┌──────────────────────────────────────────────────────────┐
│ Vault-Tracker │
│ │
│ ┌──────────┐ ┌───────────────┐ ┌──────────────┐ │
│ │ Poller │───▶│ Tracker Logic │───▶│ SQLite DB │ │
│ │ (loop) │ │ │ │ /data/*.db │ │
│ └──────────┘ └───────┬───────┘ └──────────────┘ │
│ │ │ ▲ │
│ │ ▼ │ │
│ │ ┌────────────────┐ │ │
│ └────────▶│ State Monitor │────────────┘ │
│ │ (seed detect) │ │
│ └────────────────┘ │
└──────────────────────────────────────────────────────────┘
Flow:
1. New torrent detected
2. Private tracker? ─── No ──▶ Skip
└── Yes ──▶ Save URLs to DB
Strip URLs from torrent
3. Torrent finishes downloading, enters seeding state
4. Retrieve saved URLs from DB
5. Reinject URLs into torrent
6. Torrent seeds normally with full tracker connectivity
- Docker and Docker Compose installed on your server.
- A running qBittorrent instance with the WebUI API enabled.
- Network connectivity between the Vault-Tracker container and qBittorrent's WebUI.
git clone https://github.com/adamdevlpmnt/Vault-Tracker.git
cd Vault-TrackerEdit docker-compose.yml and set your qBittorrent connection details:
environment:
QB_HOST: "http://192.168.1.100" # Your qBittorrent host
QB_PORT: "8080" # WebUI port
QB_USERNAME: "admin" # WebUI username
QB_PASSWORD: "your-password" # WebUI passworddocker compose up -dThe image is pulled automatically from ghcr.io/adamdevlpmnt/vault-tracker:latest.
docker logs -f vault-trackerYou should see:
[2026-03-13 13:00:00] [INFO ] 🚀 Vault-Tracker v1.0.0 starting
[2026-03-13 13:00:00] [INFO ] 🔌 Connected to qBittorrent WebUI → ✅ OK
[2026-03-13 13:00:00] [INFO ] 🔁 Container restart → no pending reinjections in database
[2026-03-13 13:00:01] [INFO ] 🔄 Polling cycle — 12 torrent(s) detected
All configuration is done through environment variables — no config files to manage.
| Variable | Default | Description |
|---|---|---|
QB_HOST |
http://localhost |
qBittorrent WebUI host (include http:// or https://) |
QB_PORT |
8080 |
qBittorrent WebUI port |
QB_USERNAME |
admin |
WebUI username |
QB_PASSWORD |
adminadmin |
WebUI password |
POLL_INTERVAL |
10 |
Seconds between polling cycles |
RETRY_DELAY |
30 |
Seconds to wait before retrying when qBittorrent is unreachable |
MAX_RETRIES |
0 |
Maximum retry attempts (0 = retry forever) |
DB_PATH |
/data/vault-tracker.db |
Path to the SQLite database inside the container |
LOG_LEVEL |
INFO |
Log verbosity: DEBUG, INFO, WARNING, ERROR |
Instead of editing docker-compose.yml directly, you can create a .env file:
QB_HOST=http://192.168.1.100
QB_PORT=8080
QB_USERNAME=admin
QB_PASSWORD=your-secret-password
POLL_INTERVAL=10
RETRY_DELAY=30
MAX_RETRIES=0
LOG_LEVEL=INFOThen update docker-compose.yml to use it:
services:
vault-tracker:
image: ghcr.io/adamdevlpmnt/vault-tracker:latest
container_name: vault-tracker
restart: unless-stopped
env_file: .env
volumes:
- /mnt/TANK/Config/Vault-Tracker:/dataEvery action produces a structured, timestamped log entry visible via docker logs vault-tracker.
| Emoji | Event | Description |
|---|---|---|
| 🔌 | Connection | Connecting to qBittorrent WebUI (OK / ERROR) |
| 🔄 | Poll cycle | Start of a polling cycle with torrent count |
| 🆕 | New torrent | A torrent was detected for the first time |
| 🔍 | Privacy check | Whether the torrent has private trackers |
| 💾 | Tracker saved | Tracker URL persisted to database |
| ✂️ | Tracker stripped | Tracker URL removed from active torrent |
| ⏳ | Downloading | Torrent download in progress with state |
| ✅ | Seeding | Torrent completed and entered seeding state |
| 💉 | Reinjected | Tracker URL added back to the torrent |
| Unreachable | qBittorrent connection lost, retrying | |
| 🔁 | Recovery | Container restarted, listing pending reinjections |
| 🛑 | Shutdown | Graceful shutdown initiated |
[2026-03-13 13:00:01] [INFO ] 🆕 New torrent detected: "Ubuntu 24.04" [hash: a1b2c3d4]
[2026-03-13 13:00:01] [INFO ] 🔍 Private tracker check for "Ubuntu 24.04" → private (1 tracker(s))
[2026-03-13 13:00:01] [INFO ] 💾 Tracker URL saved: https://tracker.example.com/ann?passkey=abc***456 → ✅ OK
[2026-03-13 13:00:02] [INFO ] ✂️ Tracker(s) stripped from "Ubuntu 24.04" → ✅ OK
...
[2026-03-13 13:05:12] [INFO ] ✅ Torrent completed, seeding state detected: "Ubuntu 24.04"
[2026-03-13 13:05:12] [INFO ] 💉 Tracker URL reinjected: https://tracker.example.com/ann?passkey=abc***456 → ✅ OK
The SQLite database is stored in a Docker named volume (vault-tracker-data), which persists across container restarts and rebuilds. On startup, the service:
- Reads all pending reinjections from the database.
- Checks if any of those torrents are already in a seeding state.
- Immediately reinjects trackers for completed torrents.
This means you can safely restart, update, or rebuild the container without losing any tracker data.
Vault-Tracker identifies private trackers by scanning tracker URLs for common authentication parameters:
passkey=authkey=torrent_pass=pid=secure=auth=key=user=
Any tracker URL containing one of these parameters is treated as a private tracker. Public trackers (e.g., udp://tracker.opentrackr.org:1337/announce) are left untouched.
vault-tracker/
├── vault_tracker/
│ ├── __init__.py # Package metadata
│ ├── __main__.py # Entry point (python -m vault_tracker)
│ ├── config.py # Environment variable configuration
│ ├── database.py # SQLite persistence layer
│ ├── logger.py # Structured emoji logging
│ ├── qbittorrent.py # qBittorrent WebUI API client
│ └── service.py # Core polling loop & tracker logic
├── docker-compose.yml # Deployment configuration
├── Dockerfile # Container build
├── requirements.txt # Python dependencies (requests)
├── .dockerignore
├── .gitignore
└── README.md
Tech stack:
- Python 3.12 — lightweight, readable, well-suited for I/O-bound polling.
- requests — battle-tested HTTP client for the qBittorrent API.
- SQLite (WAL mode) — zero-dependency embedded database, perfect for single-writer persistence.
- Docker — isolated, reproducible deployment.
- Verify that
QB_HOSTincludes the protocol (http://orhttps://). - Ensure the qBittorrent WebUI is enabled and listening on the configured port.
- If qBittorrent runs in Docker, make sure both containers share a network or use the host IP.
- Check your firewall rules allow traffic on
QB_PORT.
- Set
LOG_LEVEL=DEBUGfor more verbose output. - Ensure the tracker URL contains a recognized authentication parameter (see detection section above).
- Verify the qBittorrent API user has permission to modify trackers.
- The database is stored at
DB_PATHinside the container (default:/data/vault-tracker.db). - To reset:
docker volume rm vault-tracker-data— this deletes all saved tracker data. - To inspect:
docker exec vault-tracker sqlite3 /data/vault-tracker.db ".dump"
MIT