1
1
Fork
You've already forked pybittrack
0
No description
  • Python 76.1%
  • HTML 23.9%
retiolus 08fe56d2e1 fix CSRF failure behind HTTPS reverse proxy
Django behind Nginx rejects POST forms when the Referer header scheme
(https://) doesn't match the scheme uvicorn sees (http://).
- Add SECURE_PROXY_SSL_HEADER and USE_X_FORWARDED_HOST to settings so
 Django trusts the X-Forwarded-Proto header sent by Nginx
- Add CSRF_TRUSTED_ORIGINS read from config.json
- Add X-Forwarded-Proto $scheme to Nginx location block in README
- Add csrf_trusted_origins to config.json.example and README example
2026年03月19日 19:30:00 +01:00
pybittrack fix CSRF failure behind HTTPS reverse proxy 2026年03月19日 19:30:00 +01:00
templates add admin interface, optimise Redis storage, harden tracker 2026年03月18日 20:39:00 +01:00
tests add admin interface, optimise Redis storage, harden tracker 2026年03月18日 20:39:00 +01:00
tracker add admin interface, optimise Redis storage, harden tracker 2026年03月18日 20:39:00 +01:00
.gitignore transition to redis 2024年11月09日 13:30:08 +01:00
config.json.example fix CSRF failure behind HTTPS reverse proxy 2026年03月19日 19:30:00 +01:00
LICENSE Initial commit 2024年06月06日 21:36:03 +00:00
manage.py refactor: migrate from Flask to Django with modular architecture 2026年03月18日 20:37:49 +01:00
README.md fix CSRF failure behind HTTPS reverse proxy 2026年03月19日 19:30:00 +01:00
requirements.txt add admin interface, optimise Redis storage, harden tracker 2026年03月18日 20:39:00 +01:00

PyBitTrack

High-performance BitTorrent tracker built with Django + Redis. Handles 1 M+ concurrent torrents, async ASGI workers, and an admin interface.

Announce: https://your-domain/announce Scrape: https://your-domain/scrape Stats: https://your-domain/stats Admin: https://your-domain/admin/


Requirements

Component Version
Python 3.11+
Redis 6+
Nginx any recent
OS Debian/Ubuntu (or any Linux)

Installation

1. Clone

git clone https://codeberg.org/retiolus/pybittrack.git
cd pybittrack

2. Virtual environment & dependencies

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

3. Configuration

cp config.json.example config.json

Edit config.json:

{
 "host": "0.0.0.0",
 "port": 6969,
 "secret_key": "change_this_to_a_long_random_string",
 "redis": {
 "host": "localhost",
 "port": 6379,
 "db": 1,
 "password": ""
 },
 "site": {
 "title": "PyBitTrack"
 },
 "tracker": {
 "announce_interval": 900,
 "announce_min_interval": 899,
 "announce_timeout_factor": 1.25
 },
 "logging": {
 "level": "ERROR"
 },
 "csrf_trusted_origins": ["https://your-domain.tld"],
 "admin": {
 "password": "change_this_strong_password"
 }
}

Key fields:

Field Description
secret_key Django secret key — long, random, keep private
redis.db Redis DB index (0–15). Use a dedicated index, not 0.
tracker.announce_interval Seconds between client announces (900 = 15 min)
tracker.announce_timeout_factor Peer considered stale after interval ×ばつ factor
admin.password Password for the /admin/ interface

4. Verify

source venv/bin/activate
python manage.py check

Expected output: System check identified no issues (0 silenced).


Running

Development (quick test)

source venv/bin/activate
DJANGO_SETTINGS_MODULE=pybittrack.settings \
 uvicorn pybittrack.asgi:application --host 0.0.0.0 --port 6969

Remove --no-access-log during development if you want to see requests in the terminal. Always keep it in production (see note in the Nginx section).

Production — systemd service

Create /etc/systemd/system/pybittrack.service:

[Unit]
Description=PyBitTrack BitTorrent Tracker
After=network.target redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/pybittrack
Environment="DJANGO_SETTINGS_MODULE=pybittrack.settings"
ExecStart=/opt/pybittrack/venv/bin/uvicorn \
 pybittrack.asgi:application \
 --host 127.0.0.1 \
 --port 6969 \
 --workers 4 \
 --loop uvloop \
 --no-access-log
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

Adjust WorkingDirectory and ExecStart to your actual install path, then:

sudo systemctl daemon-reload
sudo systemctl enable --now pybittrack
sudo systemctl status pybittrack

Workers: --workers 4 is a good starting point. Use 2 ×ばつ CPU cores for announce-heavy traffic.


Nginx

Why disable access logs? A busy tracker receives thousands of /announce and /scrape requests per minute. Nginx access logs would grow at several GB per day and thrash the disk. Keep error logs — disable only access logs.

HTTP only (port 80/8080)

server {
 listen 80;
 server_name your-domain.tld;
 # Suppress access logs — announce/scrape volume would flood disk
 access_log off;
 location / {
 proxy_pass http://127.0.0.1:6969;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Real-IP $remote_addr;
 }
}

Install Certbot, obtain a certificate, then:

server {
 listen 80;
 server_name your-domain.tld;
 access_log off;
 return 301 https://$host$request_uri;
}
server {
 listen 443 ssl http2;
 server_name your-domain.tld;
 ssl_certificate /etc/letsencrypt/live/your-domain.tld/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/your-domain.tld/privkey.pem;
 ssl_protocols TLSv1.2 TLSv1.3;
 ssl_ciphers HIGH:!aNULL:!MD5;
 # Suppress access logs — announce/scrape volume would flood disk
 access_log off;
 # Optional: restrict admin to specific IP(s)
 # location /admin/ {
 # allow 203.0.113.10;
 # deny all;
 # proxy_pass http://127.0.0.1:6969;
 # }

 location / {
 proxy_pass http://127.0.0.1:6969;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_read_timeout 30s;
 # Required for .torrent file uploads in the admin
 client_max_body_size 10M;
 }
}

Reload Nginx:

sudo nginx -t && sudo systemctl reload nginx

Redis

Redis must be running before starting the tracker.

# Install (Debian/Ubuntu)
sudo apt install redis-server
# Recommended: set a password in /etc/redis/redis.conf
# requirepass your_redis_password
# Then update config.json → redis.password accordingly
sudo systemctl enable --now redis
redis-cli ping # should return PONG

Logging

A tracker under normal load receives tens of thousands of requests per hour. All three layers must have logging disabled or minimised, otherwise disk I/O from log writes becomes a bottleneck and storage fills up within hours.

Layer What to do Where
Nginx access_log off; in every server block /etc/nginx/sites-available/pybittrack
uvicorn --no-access-log flag systemd unit ExecStart
Django "logging": {"level": "ERROR"} in config.json config.json

Each layer logs only actual errors. Normal announces and scrapes produce no log output.

To verify nothing is accumulating after deployment:

# Nginx — should stay at 0 bytes
ls -lh /var/log/nginx/access.log
# uvicorn/systemd — only errors, no per-request lines
sudo journalctl -u pybittrack -n 50 --no-pager

Admin interface

Visit https://your-domain/admin/ and log in with the password set in config.json → admin.password.

Features:

  • Global stats (total torrents, active torrents, seeders, leechers)
  • Search by info hash (40-char hex, base32, or base64url)
  • Search by magnet link
  • Search by IP address
  • Upload a .torrent file to inspect its peers

The admin interface requires announce_interval ×ばつ announce_timeout_factor seconds of announce traffic before peers appear. Stats refresh every 15 minutes via a background thread.


Running the tests

source venv/bin/activate
DJANGO_SETTINGS_MODULE=pybittrack.settings python -m pytest tests/test_tracker.py -v

Tests use Redis DB 3 (isolated). Redis must be reachable.


License

AGPL-3.0 — see LICENSE.

Torrent ≠ Piracy. This tracker does not host or distribute any content.