Mateusz Gruszczyński 0730e7316c labels and automatizations
2026-05-06 23:00:06 +02:00
2026-05-06 08:47:20 +02:00
2026-05-06 23:00:06 +02:00
2026-05-06 11:25:41 +02:00
2026-05-06 08:47:20 +02:00
2026-05-06 11:25:41 +02:00
2026-05-06 11:25:41 +02:00
2026-05-04 10:43:31 +02:00
2026-05-06 08:50:40 +02:00
2026-05-06 11:25:41 +02:00
2026-05-06 08:38:07 +02:00
2026-05-06 08:38:07 +02:00
2026-05-04 10:43:31 +02:00
2026-05-04 10:43:31 +02:00

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

./install.sh
. venv/bin/activate
python app.py

Default URL: http://127.0.0.1:8090.

Production run

Preferred mode without development Werkzeug:

. 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:

PYTORRENT_PROXY_FIX_ENABLE=true
PYTORRENT_SESSION_COOKIE_SECURE=true

The proxy should forward at least:

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:

scgi://127.0.0.1:5000/RPC2

On the rTorrent side:

network.scgi.open_port = 127.0.0.1:5000

GeoIP

The installer downloads GeoLite2-City once to:

data/GeoLite2-City.mmdb

Manual download:

./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:

. venv/bin/activate
python -m pytorrent.cli reset-password admin new_password

Without the password argument, the CLI asks for it interactively:

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.

Description
No description provided
Readme 1.9 MiB
Languages
Python 55.9%
JavaScript 24.6%
HTML 10.5%
CSS 8.7%
Shell 0.3%