Mateusz Gruszczyński 6aea0c1ad9 fix in download torrents
2026-05-22 13:53:10 +02:00
2026-05-19 13:43:37 +00:00
2026-05-19 13:43:37 +00:00
2026-05-22 13:53:10 +02:00
2026-05-22 08:56:27 +02:00
2026-05-19 13:43:37 +00:00
2026-05-21 22:06:52 +02:00
2026-05-19 13:43:37 +00:00
2026-05-22 09:02:07 +02:00
2026-05-19 13:43:37 +00:00
2026-05-19 13:43:37 +00:00
2026-05-20 13:47:07 +02:00
2026-05-19 13:43:37 +00:00
2026-05-19 13:43:37 +00:00
2026-05-19 13:43:37 +00:00
2026-05-21 22:05:08 +02:00
2026-05-19 13:43:37 +00:00
2026-05-19 13:43:37 +00: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.

Complete Debian / Ubuntu install

The repository includes a full installer for Debian and Ubuntu:

wget -qO /tmp/install_debian_ubuntu.sh "https://git.linuxiarz.pl/gru/pyTorrent/raw/branch/master/scripts/install_debian_ubuntu.sh" && sudo bash /tmp/install_debian_ubuntu.sh

The installer installs system packages, creates the dedicated pytorrent system user, copies the app to /opt/pytorrent, creates a virtual environment, installs Python dependencies, downloads offline frontend libraries and GeoIP data when helper scripts are available, then creates and starts the pytorrent systemd service.

Optional environment variables:

PYTORRENT_USER=pytorrent \
PYTORRENT_APP_DIR=/opt/pytorrent \
PYTORRENT_SERVICE_NAME=pytorrent \
sudo -E bash scripts/install_debian_ubuntu.sh

Check the service with:

sudo systemctl status pytorrent
sudo journalctl -u pytorrent -f

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.

API authentication tokens

When PYTORRENT_AUTH_ENABLE=0, API endpoints work without authentication.

When PYTORRENT_AUTH_ENABLE=1, API access can use either the browser session cookie or a per-user API token. Admin users can generate a token in Tools -> Users with Generate token. Copy the token immediately; only its prefix and metadata are stored afterwards.

Use a token in one of these forms:

curl -H "Authorization: Bearer pt_xxx" http://127.0.0.1:8080/api/system/status
curl -H "X-API-Key: pt_xxx" http://127.0.0.1:8080/api/system/status

Token permissions follow the owning user's role and rTorrent profile permissions. Revoked tokens stop working immediately.

Description
No description provided
Readme 4 MiB
Languages
Python 77.6%
CSS 10.3%
HTML 9.7%
Shell 2%
JavaScript 0.4%