129 lines
4.9 KiB
Markdown
129 lines
4.9 KiB
Markdown
# pyTorrent
|
|
|
|
Single-page web UI for rTorrent inspired by the ruTorrent workflow.
|
|
|
|
## Features
|
|
|
|
- Flask + Flask-SocketIO.
|
|
- SQLite storage for preferences, SCGI profiles, Bootstrap theme and UI font.
|
|
- Multiple rTorrent profiles per user.
|
|
- Profiles can be added and edited from the UI; the remote profile flag hides local CPU/RAM usage to avoid confusing it with remote rTorrent host resources.
|
|
- Active rTorrent profile switching from the UI.
|
|
- Live torrent list over WebSocket.
|
|
- Application-side cache with patch updates instead of full table reloads.
|
|
- User operations executed through ThreadPoolExecutor.
|
|
- `move` and `remove` actions are executed per profile in request order, so later deletes wait for earlier moves.
|
|
- Job log shows a short date/time in the table and the full timestamp in the tooltip.
|
|
- Bulk start, pause, stop, resume, recheck, remove and move.
|
|
- Move supports `move_data=true`; data is physically moved on the rTorrent side in the background and status is polled from a marker file, so long `mv` operations do not hit the SCGI timeout.
|
|
- Multi-magnet add modal.
|
|
- Bottom status bar with CPU, RAM, rTorrent version, speeds, limits, total DL/UP and port-check status when enabled.
|
|
- Torrent context menu.
|
|
- Keyboard shortcuts.
|
|
- Details tabs: General, Files, Peers, Trackers and Log.
|
|
- Smart Queue shows the last 10 operations by default and can expand history to 100 rows.
|
|
- Peer GeoIP with MaxMind GeoLite2-City.mmdb and IP cache.
|
|
- Static cache busting with MD5 and cache headers.
|
|
- Appearance preferences: default Bootstrap or Bootswatch themes Flatly, Litera, Lumen, Minty, Sketchy, Solar, Spacelab, United and Zephyr.
|
|
- Font preferences: default theme font, Adwaita Mono and additional matching fonts.
|
|
|
|
## Run locally
|
|
|
|
```bash
|
|
./install.sh
|
|
. venv/bin/activate
|
|
python app.py
|
|
```
|
|
|
|
Default URL: `http://127.0.0.1:8090`.
|
|
|
|
## Production run
|
|
|
|
Preferred mode without development Werkzeug:
|
|
|
|
```bash
|
|
. venv/bin/activate
|
|
gunicorn --worker-class gthread --workers 1 --threads 32 --bind 0.0.0.0:8090 --access-logfile - --error-logfile - wsgi:app
|
|
```
|
|
|
|
Note: the app keeps `async_mode="threading"`, so WebSocket, `start_background_task`, operation queues and the poller run in the same model as before.
|
|
|
|
Alternatives reviewed but not enabled by default:
|
|
|
|
- Gunicorn with `eventlet`: works with Flask-SocketIO, but requires green threads and monkey patching, which increases regression risk for file and SCGI operations.
|
|
- Gunicorn with `gevent`: a valid production option, but it needs extra dependencies and compatibility testing.
|
|
- Multiple Gunicorn workers: requires Redis, RabbitMQ or Kafka as the Socket.IO message queue, so it is not a drop-in replacement.
|
|
|
|
## Reverse proxy
|
|
|
|
When pyTorrent is served behind a reverse proxy, enable proxy header handling only when the proxy is trusted:
|
|
|
|
```env
|
|
PYTORRENT_PROXY_FIX_ENABLE=true
|
|
PYTORRENT_SESSION_COOKIE_SECURE=true
|
|
```
|
|
|
|
The proxy should forward at least:
|
|
|
|
```txt
|
|
X-Forwarded-For
|
|
X-Forwarded-Proto
|
|
X-Forwarded-Host
|
|
X-Forwarded-Port
|
|
```
|
|
|
|
This keeps login redirects, session cookies and same-origin API checks correct when HTTPS is terminated by the proxy. If pyTorrent is mounted under a sub-path, also forward `X-Forwarded-Prefix`.
|
|
|
|
## SCGI profile
|
|
|
|
Example:
|
|
|
|
```txt
|
|
scgi://127.0.0.1:5000/RPC2
|
|
```
|
|
|
|
On the rTorrent side:
|
|
|
|
```txt
|
|
network.scgi.open_port = 127.0.0.1:5000
|
|
```
|
|
|
|
## GeoIP
|
|
|
|
The installer downloads GeoLite2-City once to:
|
|
|
|
```txt
|
|
data/GeoLite2-City.mmdb
|
|
```
|
|
|
|
Manual download:
|
|
|
|
```bash
|
|
./scripts/download_geoip.sh
|
|
```
|
|
|
|
The script uses `https://git.io/GeoLite2-City.mmdb` as the primary source and `https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb` as fallback. The `data` directory is set to `755`, and the database file is set to `644`.
|
|
|
|
## API docs
|
|
|
|
OpenAPI documentation is available at `/docs`. `/api/profiles` supports `max_parallel_jobs` with default value `5` and `is_remote`; `PUT /api/profiles/{profile_id}` edits an existing profile. `/api/preferences` supports fields including `theme`, `bootstrap_theme`, `font_family`, `table_columns_json`, `peers_refresh_seconds` and `port_check_enabled`. `/api/port-check` returns port status with `checked_at`; for remote profiles the public IP is read through rTorrent with fallbacks when supported. `/api/system/status` returns `usage_available=false` for remote profiles and does not read local CPU/RAM.
|
|
|
|
`/api/openapi.json` includes reusable schemas for main API responses, including `TorrentListResponse`, `TorrentSummary`, `TorrentFilterSummary`, `CleanupSummary` and `AppStatus`. `GET /api/torrents` documents the `summary` field used by sidebar filters.
|
|
|
|
## Admin CLI
|
|
|
|
Reset an existing user's password:
|
|
|
|
```bash
|
|
. venv/bin/activate
|
|
python -m pytorrent.cli reset-password admin new_password
|
|
```
|
|
|
|
Without the password argument, the CLI asks for it interactively:
|
|
|
|
```bash
|
|
python -m pytorrent.cli reset-password admin
|
|
```
|
|
|
|
The command uses the same database as the app and respects `PYTORRENT_DB_PATH` from `.env`. The reset changes only the password hash and leaves role and permissions unchanged.
|