163 lines
5.1 KiB
Markdown
163 lines
5.1 KiB
Markdown
# Torrent Faker
|
||
|
||
Fake BitTorrent seeder — announces upload statistics to real trackers without transferring any actual data.
|
||
|
||
Useful for keeping a torrent "alive" on a tracker, testing tracker behavior, or load-testing tracker infrastructure without consuming bandwidth.
|
||
|
||
## Features
|
||
|
||
- Announces to HTTP/HTTPS trackers (BEP 3) and UDP trackers (BEP 15)
|
||
- Simulates realistic upload speeds with jitter, burst, and stall events
|
||
- Impersonates real BitTorrent clients (qBittorrent, Transmission)
|
||
- Web UI for managing torrents and viewing live stats
|
||
- REST API for programmatic control
|
||
- CLI for quick command-line use
|
||
- Docker support
|
||
|
||
## Prerequisites
|
||
|
||
**Option A — Bun (native):** [Bun](https://bun.sh) ≥ 1.0
|
||
|
||
**Option B — Docker:** Docker + Docker Compose
|
||
|
||
## Quick Start
|
||
|
||
### Docker (recommended)
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
Drop `.torrent` files into the `torrents/` directory — they are loaded automatically.
|
||
|
||
Access the web UI at <http://localhost:3000>.
|
||
|
||
### Native (Bun)
|
||
|
||
```bash
|
||
# Install dependencies
|
||
bun install
|
||
|
||
# Build the UI
|
||
bun run build:ui
|
||
|
||
# Start the server
|
||
bun run start
|
||
```
|
||
|
||
The server starts on port 3000 by default.
|
||
|
||
## Configuration
|
||
|
||
Copy the default config and edit as needed:
|
||
|
||
```bash
|
||
cp src/config/config.default.yml config/config.yml
|
||
```
|
||
|
||
| Field | Default | Description |
|
||
|-----------------------------|--------------|-----------------------------------------------|
|
||
| `port` | `3000` | HTTP port for the web UI and REST API |
|
||
| `announcePort` | `6881` | Port reported to trackers in announce requests |
|
||
| `minUploadRateBytesPerSec` | `524288` | Minimum simulated upload speed (512 KB/s) |
|
||
| `maxUploadRateBytesPerSec` | `2097152` | Maximum simulated upload speed (2 MB/s) |
|
||
| `clientProfile` | `qbittorrent`| Client to impersonate: `qbittorrent` or `transmission` |
|
||
| `torrentsDir` | `./torrents` | Directory scanned for `.torrent` files |
|
||
| `autoLoad` | `true` | Auto-load all torrents in `torrentsDir` on startup |
|
||
|
||
Configuration can also be updated at runtime via the web UI or `PATCH /api/config`.
|
||
|
||
## Web UI
|
||
|
||
The web UI is served at the root URL and provides:
|
||
|
||
- Live upload stats per torrent (speed, total uploaded, seeders/leechers)
|
||
- Global stats panel (active seeders, total uploaded, uptime)
|
||
- Add torrents by file upload
|
||
- Remove torrents
|
||
- Edit configuration settings
|
||
|
||
Stats update in real time via Server-Sent Events.
|
||
|
||
## CLI
|
||
|
||
The CLI requires a running server instance.
|
||
|
||
```bash
|
||
# Add and start seeding a torrent
|
||
bun run cli add ./torrents/example.torrent
|
||
|
||
# List all active torrents
|
||
bun run cli list
|
||
|
||
# Remove a torrent (info hash or prefix)
|
||
bun run cli remove a1b2c3d4
|
||
|
||
# Show global stats
|
||
bun run cli status
|
||
```
|
||
|
||
Set `TORRENT_FAKER_API` to point to a non-local server:
|
||
|
||
```bash
|
||
TORRENT_FAKER_API=http://my-server:3000 bun run cli list
|
||
```
|
||
|
||
## REST API
|
||
|
||
| Method | Path | Description |
|
||
|----------|---------------------------|--------------------------------------------|
|
||
| `GET` | `/api/torrents` | List all active torrents |
|
||
| `POST` | `/api/torrents` | Upload a `.torrent` file (`multipart/form-data`, field: `torrent`) |
|
||
| `GET` | `/api/torrents/:hash` | Stats and announce history for one torrent |
|
||
| `DELETE` | `/api/torrents/:hash` | Stop seeding and remove a torrent |
|
||
| `GET` | `/api/status` | Global stats snapshot |
|
||
| `GET` | `/api/status/stream` | SSE stream for live updates |
|
||
| `GET` | `/api/config` | Current configuration |
|
||
| `PATCH` | `/api/config` | Update mutable configuration fields |
|
||
|
||
### Add a torrent via curl
|
||
|
||
```bash
|
||
curl -X POST http://localhost:3000/api/torrents \
|
||
-F "torrent=@./example.torrent"
|
||
```
|
||
|
||
### SSE stream events
|
||
|
||
Connect to `/api/status/stream` to receive:
|
||
|
||
- `stats` — global stats on every change
|
||
- `torrent` — per-torrent state on each announce
|
||
- `torrents` — full torrent list on initial connection
|
||
- `ping` — keep-alive every 30 seconds
|
||
|
||
## Client Profiles
|
||
|
||
| Profile | Peer ID prefix | User-Agent |
|
||
|----------------|----------------|-----------------------|
|
||
| `qbittorrent` | `-qB4520-` | `qBittorrent/4.5.2` |
|
||
| `transmission` | `-TR3000-` | `Transmission/3.00` |
|
||
|
||
Each seeder session uses a unique randomly-generated peer ID.
|
||
|
||
## Development
|
||
|
||
```bash
|
||
bun run dev # Start server with hot-reload
|
||
bun test # Run tests
|
||
bun run lint # Lint with Biome
|
||
bun run format # Auto-format with Biome
|
||
bun run build:ui # Build Svelte UI to ui/dist/
|
||
```
|
||
|
||
## Speed Simulation
|
||
|
||
Each torrent picks a random base upload rate within the configured min/max range. Per announce interval (every ~5 seconds):
|
||
|
||
- Normal: ±15% Gaussian-like noise around the base rate
|
||
- 5% chance: burst to 150–200% of base rate
|
||
- 3% chance: stall to 0–10% of base rate
|
||
|
||
This produces upload curves that resemble real client behavior.
|