initial commit
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
---
|
||||
name: private-tracker-seedbox
|
||||
description: |-
|
||||
Deploy and troubleshoot a Docker seedbox for private trackers — gluetun VPN,
|
||||
qBittorrent, PIA port forwarding, and tracker-specific authorization
|
||||
(MAM Dynamic Seedbox via Mousehole).
|
||||
version: 1.0.0
|
||||
platforms: [linux]
|
||||
tags: [seedbox, torrent, qbittorrent, gluetun, vpn, private-tracker, mam, myanonamouse]
|
||||
---
|
||||
|
||||
# Private Tracker Seedbox
|
||||
|
||||
Deploying a Docker seedbox for private trackers with gluetun (VPN) + qBittorrent,
|
||||
plus tracker-specific tooling for IP authorization when the torrent client's IP
|
||||
differs from the browser's IP.
|
||||
|
||||
## Gluetun + qBittorrent Base Setup
|
||||
|
||||
### Docker Compose Pattern
|
||||
|
||||
```yaml
|
||||
services:
|
||||
gluetun:
|
||||
image: qmcgaw/gluetun:latest
|
||||
container_name: gluetun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
ports:
|
||||
- 127.0.0.1:11893:8080 # qBittorrent WebUI
|
||||
- 127.0.0.1:6881:6881 # torrent port (optional, qBittorrent uses forwarded port)
|
||||
- 127.0.0.1:6881:6881/udp # (optional)
|
||||
- 127.0.0.1:5010:5010 # Mousehole WebUI (if used)
|
||||
volumes:
|
||||
- ./gluetun:/gluetun
|
||||
environment:
|
||||
VPN_SERVICE_PROVIDER: "private internet access"
|
||||
VPN_TYPE: "openvpn"
|
||||
OPENVPN_PROTOCOL: "tcp"
|
||||
OPENVPN_ENDPOINT_PORT: "443"
|
||||
OPENVPN_USER: "your-username"
|
||||
OPENVPN_PASSWORD: your-password
|
||||
UPDATER_PERIOD: "0"
|
||||
SERVER_HOSTNAMES: "nl-amsterdam.privacy.network" # PIA server
|
||||
VPN_PORT_FORWARDING: "on" # PIA port forwarding
|
||||
PORT_FORWARD_ONLY: "true" # only allow port-forwarded ports
|
||||
FIREWALL_VPN_INPUT_PORTS: "8080,5010" # comma-separated allowed ports
|
||||
restart: unless-stopped
|
||||
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
network_mode: "service:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./qbittorrent:/config
|
||||
- /path/to/downloads:/downloads
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Chicago
|
||||
- WEBUI_PORT=8080
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### Key Config Points
|
||||
|
||||
- qBittorrent uses `network_mode: "service:gluetun"` — shares gluetun's network stack
|
||||
- `depends_on: gluetun: condition: service_healthy` — waits for VPN tunnel before starting
|
||||
- qBittorrent's listening port (from `Session\Port` in qBittorrent.conf) must match gluetun's forwarded port from the VPN provider
|
||||
- Port **11893** on host maps to qBittorrent WebUI at port 8080 inside gluetun's stack
|
||||
|
||||
### Compose Gotcha: `restart` vs `up -d`
|
||||
|
||||
**`docker compose restart <svc>` restarts the existing container with its ORIGINAL config.**
|
||||
It does NOT pick up changes to port mappings, environment variables, or volumes.
|
||||
To apply compose changes, use:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This recreates any container whose config has changed. If you need to force even when
|
||||
the config hasn't changed:
|
||||
|
||||
```
|
||||
docker compose up -d --force-recreate <svc>
|
||||
```
|
||||
|
||||
### Port Binding: localhost-only vs All Interfaces
|
||||
|
||||
- `127.0.0.1:5010:5010` — binds ONLY to localhost; accessible from host only
|
||||
- `5010:5010` — binds to 0.0.0.0 (all interfaces); accessible from LAN and other Docker
|
||||
containers (e.g., KasmVNC Chrome)
|
||||
|
||||
When running Chrome in a KasmVNC container that's on a different Docker network,
|
||||
the browser uses its own network namespace. `localhost` inside KasmVNC refers to
|
||||
KasmVNC itself, not the host. Use the host's LAN IP (e.g., `192.168.50.98:5010`)
|
||||
and ensure the port is bound to all interfaces.
|
||||
|
||||
To verify actual Docker port bindings:
|
||||
```
|
||||
docker port <container>
|
||||
```
|
||||
|
||||
## PIA Port Forwarding
|
||||
|
||||
PIA port forwarding with gluetun:
|
||||
|
||||
1. Set `VPN_PORT_FORWARDING: "on"` and `PORT_FORWARD_ONLY: "true"` on gluetun
|
||||
2. Gluetun logs show the forwarded port (e.g., `port forwarded is 36590`)
|
||||
3. The forwarded port is written to `/tmp/gluetun/forwarded_port` inside gluetun
|
||||
4. qBittorrent must use this port — set `Session\Port=<forwarded port>` in qBittorrent.conf
|
||||
|
||||
Check forwarded port:
|
||||
```
|
||||
docker exec gluetun cat /tmp/gluetun/forwarded_port
|
||||
```
|
||||
|
||||
## MAM (MyAnonaMouse) — Dynamic Seedbox / Mousehole
|
||||
|
||||
### The Problem
|
||||
|
||||
MAM compares your **browser's IP** against your **torrent client's IP**. If they don't match
|
||||
(e.g., browser on home IP, torrent client on VPN IP), you get:
|
||||
> **"Unrecognized host/PassKey. (client IP here)"**
|
||||
|
||||
### Step 1: Get Staff Approval
|
||||
|
||||
Open a ticket with MAM staff explaining you use a VPN for your torrent client.
|
||||
Per MAM rule 1.2, VPN use must be authorized.
|
||||
|
||||
### Step 2: Deploy Mousehole as a Sidecar
|
||||
|
||||
[Mousehole](https://github.com/t-mart/mousehole) is a background service that periodically
|
||||
calls MAM's Dynamic Seedbox API to register your current VPN IP.
|
||||
|
||||
Add to your docker-compose.yml:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
# ... gluetun and qbittorrent as above ...
|
||||
|
||||
mousehole:
|
||||
image: tmmrtn/mousehole:latest
|
||||
container_name: mousehole
|
||||
network_mode: "service:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
TZ: America/Chicago
|
||||
MOUSEHOLE_AUTH_PASSWORD: your-strong-password
|
||||
volumes:
|
||||
- mousehole:/var/lib/mousehole
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mousehole:
|
||||
```
|
||||
|
||||
Also add `- 127.0.0.1:5010:5010` to gluetun's `ports:` and add `,5010` to
|
||||
`FIREWALL_VPN_INPUT_PORTS`.
|
||||
|
||||
### Step 3: Configure Mousehole
|
||||
|
||||
1. Browse to **http://localhost:5010**
|
||||
2. Log in with the password set in `MOUSEHOLE_AUTH_PASSWORD`
|
||||
3. Get your MAM session cookie:
|
||||
- Log in to MAM in your browser
|
||||
- DevTools → Application/Storage → Cookies → `myanonamouse.net`
|
||||
- Copy the **session** cookie value
|
||||
4. Paste it into Mousehole's web UI
|
||||
5. Click **Update Now** to immediately register your current VPN IP
|
||||
|
||||
Mousehole will now automatically keep MAM updated with your VPN IP on a schedule.
|
||||
|
||||
### MAM Tracker Info
|
||||
|
||||
- Allowed qBittorrent: from 5.0.1 to latest 5.2.x line
|
||||
- qBittorrent Anonymous Mode will break tracker communication
|
||||
- The tracker returns bencoded responses; HTTP 200 + "failure reason" means the tracker
|
||||
accepted the request but rejected the client/IP/credentials
|
||||
- Passkey is embedded in the announce URL, not sent as a GET parameter
|
||||
|
||||
## Port Blacklist Notes
|
||||
|
||||
MAM (and many private trackers) block common P2P ports (6881-6889, etc.).
|
||||
Configure qBittorrent to use the VPN's forwarded port instead of defaults.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tracker returns "Non-Whitelisted client or version"
|
||||
- Check the MAM Allowed Clients page: the client version may not be whitelisted yet
|
||||
- Even if the web page says it's allowed, the tracker filter may lag behind
|
||||
- Verify qBittorrent is not in Anonymous Mode
|
||||
|
||||
### Tracker returns "Unrecognized host/PassKey"
|
||||
- Browser IP ≠ torrent client IP
|
||||
- Use Mousehole (Dynamic Seedbox API) to register the torrent client's IP
|
||||
|
||||
### qBittorrent logging shows no tracker announcements
|
||||
- Check that the torrent isn't paused
|
||||
- Verify qBittorrent's listening port matches the VPN forwarded port
|
||||
- Confirm `disable_dht = 0` is set correctly in the fastresume for private torrents
|
||||
(private torrents should have DHT disabled)
|
||||
|
||||
### Torrent stalled with no peers
|
||||
- Confirm port forwarding is active via `docker exec gluetun cat /tmp/gluetun/forwarded_port`
|
||||
- Test tracker reachability: `docker exec qbittorrent curl -s -o /dev/null -w "%{http_code}" <tracker_url>`
|
||||
- Verify the passkey in the announce URL is correct (check fastresume via `strings`)
|
||||
|
||||
## References
|
||||
|
||||
- [Mousehole GitHub](https://github.com/t-mart/mousehole)
|
||||
- [Gluetun Wiki](https://github.com/qdm12/gluetun-wiki)
|
||||
- [MAM FAQ — Unrecognized host/PassKey](https://s.mrd.ninja/upmm)
|
||||
- [MAM Allowed Clients](https://s.mrd.ninja/CLNTe)
|
||||
@@ -0,0 +1,108 @@
|
||||
# MAM (MyAnonaMouse) Troubleshooting Reference
|
||||
|
||||
## Tracker Error: "Unrecognized host/PassKey"
|
||||
|
||||
**Full error from MAM's tracker detail page:**
|
||||
```
|
||||
ip port agent error
|
||||
181.214.x.x 36590 -qB5230- / 5.2.3 Unrecognized host/PassKey. (181.214.x.x)
|
||||
```
|
||||
|
||||
**Root cause:** Browser IP ≠ torrent client IP. MAM compares the IP you're browsing
|
||||
from against the IP your torrent client is announcing from. When they don't match
|
||||
(e.g., browser on home connection, torrent client on VPN), the passkey is rejected
|
||||
even though the passkey itself and the client version are valid.
|
||||
|
||||
**MAM FAQ reference:**
|
||||
> *"If you are running your client over a VPN, but not your browser (or browser is
|
||||
> on a different vpn tunnel), such as a docker container that also runs the vpn,
|
||||
> you'll first need to be approved to use a VPN by staff (per rule 1.2). Then
|
||||
> you'll want to use the Dynamic Seedbox endpoint to manage the client on a
|
||||
> non-matching IP."*
|
||||
|
||||
**Resolution:**
|
||||
1. Get staff approval via MAM ticket system
|
||||
2. Set up [Mousehole](https://github.com/t-mart/mousehole) to call the Dynamic
|
||||
Seedbox API: `https://www.myanonamouse.net/api/endpoint.php/3/json/dynamicSeedbox.php`
|
||||
|
||||
## Tracker Error: "Non-Whitelisted client or version"
|
||||
|
||||
**Bencoded tracker response:**
|
||||
```
|
||||
d8:intervali86400e12:min intervali86400e8:retry ini86400e14:failure reason58:Non-Whitelisted client or version https://s.mrd.ninja/CLNTe
|
||||
```
|
||||
|
||||
**Check the allowed clients page:** https://s.mrd.ninja/CLNTe
|
||||
|
||||
**qBittorrent status on MAM:**
|
||||
- Allowed: from 5.0.1 to latest 5.2.x line (confirmed as of 2026-07-09)
|
||||
- qBittorrent Anonymous Mode IS rejected by MAM
|
||||
- Peer ID format: `-qB5230-` for 5.2.3 on non-Windows
|
||||
- User-agent: `qBittorrent/5.2.3`
|
||||
|
||||
**Known caveat:** The tracker-level whitelist filter may lag behind the web page.
|
||||
If a new version is on the web whitelist but still getting rejected, there may be
|
||||
a propagation delay.
|
||||
|
||||
## Fastresume Fields (via `strings`)
|
||||
|
||||
Key fields in `.fastresume` files that matter for troubleshooting:
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| `paused` | 0 = active, 1 = paused |
|
||||
| `disable_dht` | 0 = DHT enabled (should be 1 for private trackers) |
|
||||
| `num_complete` | seeders count, 16777215 = sentinel (unknown) |
|
||||
| `num_incomplete` | leechers count, 16777215 = sentinel (unknown) |
|
||||
| `total_downloaded` | bytes downloaded so far |
|
||||
| `active_time` | seconds the torrent has been active |
|
||||
| `last_seen_complete` | 0 = never seen a complete copy |
|
||||
| `last_download` | 0 = no downloads |
|
||||
|
||||
Ben code sentinel value 16777215 (0xFFFFFF) means "no data" — the tracker hasn't
|
||||
returned peer information.
|
||||
|
||||
## Dynamic Seedbox API
|
||||
|
||||
- **Endpoint:** `https://www.myanonamouse.net/api/endpoint.php/3/json/dynamicSeedbox.php`
|
||||
- **Requires:** Valid MAM session cookie
|
||||
- **Purpose:** Registers the current IP of the calling client as an authorized
|
||||
seedbox IP for the user's account
|
||||
- **Frequency:** Called periodically by Mousehole (handled automatically once
|
||||
configured)
|
||||
|
||||
### Docker Compose Patterns
|
||||
|
||||
### Adding Mousehole as a sidecar to existing gluetun + qBittorrent
|
||||
|
||||
Required changes to an existing docker-compose.yml:
|
||||
|
||||
1. **Gluetun ports:** add `- 127.0.0.1:5010:5010` (or `- 5010:5010` for LAN/KasmVNC access)
|
||||
2. **Gluetun environment:** add `,5010` to `FIREWALL_VPN_INPUT_PORTS`
|
||||
3. **New service:** add the mousehole service with `network_mode: "service:gluetun"`
|
||||
4. **New volume:** add a `mousehole:` volume for cookie persistence
|
||||
|
||||
The mousehole service does NOT need to communicate with qBittorrent — it only
|
||||
talks to the MAM API. It shares gluetun's network stack so outbound traffic goes
|
||||
through the VPN tunnel.
|
||||
|
||||
### Docker Port Binding
|
||||
|
||||
When `docker compose restart` doesn't pick up compose file changes:
|
||||
|
||||
```
|
||||
# This restarts with OLD config:
|
||||
docker compose restart gluetun
|
||||
|
||||
# This recreates with NEW config:
|
||||
docker compose up -d gluetun
|
||||
```
|
||||
|
||||
To verify what ports are actually bound:
|
||||
```
|
||||
docker port gluetun
|
||||
```
|
||||
|
||||
`127.0.0.1:5010` binding means host-only. If accessing from KasmVNC or another
|
||||
Docker container, the port must bind to 0.0.0.0 (specify just `5010:5010` in
|
||||
compose without an IP prefix).
|
||||
Reference in New Issue
Block a user