This guide provides Tracker-specific verification steps for manual E2E testing. For the complete deployment workflow, see the Manual E2E Testing Guide.
This guide covers:
- HTTP tracker announce/scrape endpoint testing
- UDP tracker endpoint testing (overview and future tooling)
- Tracker REST API testing
- Health check verification
- Tracker-specific troubleshooting
Complete the standard deployment workflow first (see Manual E2E Testing Guide):
- ✅ Environment created
- ✅ Infrastructure provisioned
- ✅ Services configured
- ✅ Software released
- ✅ Services running
Your environment configuration must include tracker settings:
{
"tracker": {
"core": {
"database": {
"driver": "sqlite3",
"database_name": "tracker.db"
}
},
"udp_trackers": [
{
"bind_address": "0.0.0.0:6969"
}
],
"http_trackers": [
{
"bind_address": "0.0.0.0:7070"
}
],
"http_api": {
"bind_address": "0.0.0.0:1212",
"admin_token": "MyAccessToken"
}
}
}This section provides detailed tracker verification steps that should be performed after completing the standard deployment workflow.
Extract the instance IP from the environment state (see main guide for details):
cat data/<env-name>/environment.json | jq -r '.Running.context.runtime_outputs.instance_ip'💡 Tip: A
showcommand is planned (issue #241) that will display environment information including the IP address in a more user-friendly format.
SSH into the VM and check that the tracker container is running:
# SSH into the VM
ssh -i fixtures/testing_rsa -o StrictHostKeyChecking=no torrust@<VM_IP>
# Check running containers
docker psExpected output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
acb7e4fe0569 torrust/tracker:develop "/usr/local/bin/entr…" 32 minutes ago Up 32 minutes (healthy) 0.0.0.0:1212->1212/tcp, [::]:1212->1212/tcp, 0.0.0.0:7070->7070/tcp, [::]:7070->7070/tcp, 1313/tcp, 0.0.0.0:6969->6969/udp, [::]:6969->6969/udp tracker
Key verification points:
- ✅
torrust/tracker:developcontainer is present - ✅ Container status shows "Up" with "(healthy)" indicator
- ✅ UDP port 6969 is exposed (
0.0.0.0:6969->6969/udp) - ✅ HTTP port 7070 is exposed (
0.0.0.0:7070->7070/tcp) - ✅ API port 1212 is exposed (
0.0.0.0:1212->1212/tcp)
Verify the HTTP tracker health endpoint responds:
# From your local machine
export VM_IP=<your-vm-ip>
# Test HTTP tracker health
curl http://$VM_IP:7070/health_checkExpected response:
{ "status": "Ok" }Verification points:
- ✅ HTTP 200 OK status code
- ✅ JSON response with
"status":"Ok"(note the capital 'O') - ✅ Response received within 1-2 seconds
Verify the REST API health endpoint responds:
# Test API health
curl http://$VM_IP:1212/api/health_checkExpected response:
{ "status": "Ok" }Verification points:
- ✅ HTTP 200 OK status code
- ✅ JSON response with
"status":"Ok"(note the capital 'O')
Alternative API endpoints to verify:
# Get tracker statistics
curl http://$VM_IP:1212/api/v1/stats?token=MyAccessToken
# Get Prometheus metrics
curl http://$VM_IP:1212/api/v1/metrics?token=MyAccessTokenTest the HTTP tracker announce endpoint with a sample announce request:
# Test announce endpoint
curl "http://$VM_IP:7070/announce?info_hash=%3B%24U%04%CF%5F%11%BB%DB%E1%20%1C%EAjk%F4Z%EE%1B%C0&peer_id=-qB00000000000000001&port=17548&uploaded=0&downloaded=0&left=0&event=started"Expected response (bencoded):
d8:completei1e10:incompletei0e8:intervali300e12:min intervali300e5:peerslee
This is a valid bencoded dictionary response indicating:
complete: 1 seederincomplete: 0 leechersinterval: 300 seconds (time before next announce)min interval: 300 secondspeers: Empty list (no other peers to return)
Note about reverse proxy mode:
If your tracker is configured with on_reverse_proxy = true, you'll need to include the X-Forwarded-For header:
curl -H "X-Forwarded-For: 203.0.113.195" \
"http://$VM_IP:7070/announce?info_hash=%3B%24U%04%CF%5F%11%BB%DB%E1%20%1C%EAjk%F4Z%EE%1B%C0&peer_id=-qB00000000000000001&port=17548&uploaded=0&downloaded=0&left=0&event=started"Without this header, you'll get an error:
d14:failure reason208:Error resolving peer IP: missing or invalid the right most X-Forwarded-For IP (mandatory on reverse proxy tracker configuration)e
Test the scrape endpoint to get torrent statistics:
# Test scrape endpoint
curl "http://$VM_IP:7070/scrape?info_hash=%3B%24U%04%CF%5F%11%BB%DB%E1%20%1C%EAjk%F4Z%EE%1B%C0"Expected response (bencoded):
d5:filesd20:;$U04CF5F11BBDBE1201CEAjkF4ZEE1BC0d8:completei1e10:downloadedi0e10:incompletei0eeee
This shows statistics for the torrent:
complete: 1 (number of seeders)downloaded: 0 (number of completed downloads)incomplete: 0 (number of leechers)
Note: Same reverse proxy considerations apply - add X-Forwarded-For header if needed.
Test various REST API endpoints:
curl "http://$VM_IP:1212/api/v1/stats?token=MyAccessToken" | jqExpected response:
{
"torrents": 1,
"seeders": 1,
"completed": 0,
"leechers": 0,
"tcp4_connections_handled": 12,
"tcp4_announces_handled": 11,
"tcp4_scrapes_handled": 1,
"tcp6_connections_handled": 0,
"tcp6_announces_handled": 0,
"tcp6_scrapes_handled": 0,
"udp4_connections_handled": 377,
"udp4_announces_handled": 0,
"udp4_scrapes_handled": 0,
"udp4_requests": 377,
"udp6_connections_handled": 0,
"udp6_announces_handled": 0,
"udp6_scrapes_handled": 0,
"udp6_requests": 0
}curl "http://$VM_IP:1212/api/v1/metrics?token=MyAccessToken"Expected response (JSON format with metrics):
{
"metrics": [
{
"type": "counter",
"name": "udp_tracker_server_connection_id_errors_total",
"help": "Total number of connection ID errors in the UDP tracker server",
"samples": [{ "labels": {}, "value": 0.0 }]
},
{
"type": "counter",
"name": "tracker_core_persistent_torrents_downloads_total",
"help": "Total number of torrents successfully downloaded to tracker persistent storage",
"samples": [{ "labels": {}, "value": 0.0 }]
},
{
"type": "counter",
"name": "swarm_coordination_registry_peers_added_total",
"help": "Total number of peers added to the registry",
"samples": [
{ "labels": { "peer_type": "seeder" }, "value": 11.0 },
{ "labels": { "peer_type": "leecher" }, "value": 0.0 }
]
}
]
}Note: The metrics endpoint returns JSON format containing an array of metric objects. Each metric includes type, name, help text, and sample values with optional labels.
Testing the UDP tracker requires a BitTorrent UDP protocol client. While HTTP endpoints can be easily tested with curl, UDP requires specialized tooling.
The Torrust Tracker project includes a UDP client implementation at:
- Repository: https://github.com/torrust/torrust-tracker
- Path:
console/tracker-client(indevelopbranch) - Status: Not yet published as a crate
To test UDP tracker functionality:
-
Clone the tracker repository:
git clone https://github.com/torrust/torrust-tracker.git cd torrust-tracker git checkout develop -
Run the UDP client:
cd console/tracker-client cargo run -- udp --tracker-url "udp://$VM_IP:6969" \ --info-hash "3B2455044CF55F11BBDBE1201CEA6A6BF45AEE1BC0"
-
Expected behavior:
- Connection to UDP tracker succeeds
- Announce request returns peer list
- Scrape request returns torrent statistics
For basic UDP connectivity testing without the specialized client:
# Test if UDP port is open (from local machine)
nc -u -v -w3 $VM_IP 6969
# Note: This only tests connectivity, not protocol compliance
# The tracker won't respond to arbitrary UDP packets📋 Note: The UDP tracker client will be published as a standalone Rust crate in a future release, making UDP testing much easier. Once published, you'll be able to install it with:
cargo install torrust-tracker-client torrust-tracker-client udp --tracker-url "udp://$VM_IP:6969" --info-hash <hash>
Check tracker logs for any errors or warnings:
# SSH into the VM
ssh -i fixtures/testing_rsa -o StrictHostKeyChecking=no torrust@<VM_IP>
# View tracker logs
docker logs tracker
# Follow logs in real-time
docker logs -f trackerLook for:
- ✅ No ERROR level messages
- ✅ Successful announce/scrape operations
- ✅ Health check requests logged
- ✅ UDP and HTTP servers handling requests successfully
Example healthy log output:
2025-12-20T20:10:38.800766Z INFO request{method=GET uri=/api/health_check version=HTTP/1.1}: API: request method=GET uri=/api/health_check request_id=50ea1dc8-fce1-4941-8fdd-7af67af8464d
2025-12-20T20:10:38.800889Z INFO request{method=GET uri=/api/health_check version=HTTP/1.1}: API: response latency_ms=0 status_code=200 OK server_socket_addr=0.0.0.0:1212 request_id=50ea1dc8-fce1-4941-8fdd-7af67af8464d
2025-12-20T20:10:38.801562Z INFO request{method=GET uri=/health_check version=HTTP/1.1}: HEALTH CHECK API: response latency_ms=35 status_code=200 OK request_id=1e842d0e-ee0a-47ef-b8fd-22d541a4c723
2025-12-20T20:10:38.836476Z INFO torrust_tracker_swarm_coordination_registry::swarm::registry: active_peers_total=1 inactive_peers_total=0 active_torrents_total=1 inactive_torrents_total=0
2025-12-20T20:10:43.888743Z INFO request{method=GET uri=/health_check version=HTTP/1.1}: HTTP TRACKER: request server_socket_addr=0.0.0.0:7070 method=GET uri=/health_check request_id=4e8be641-fc3d-4551-a929-10e347f7b8ba
2025-12-20T20:10:43.888770Z INFO request{method=GET uri=/health_check version=HTTP/1.1}: HTTP TRACKER: response server_socket_addr=0.0.0.0:7070 latency_ms=0 status_code=200 OK request_id=4e8be641-fc3d-4551-a929-10e347f7b8ba
Symptoms:
docker psdoesn't show tracker container- Health checks timeout or fail
Diagnosis:
# Check if container exists (including stopped)
docker ps -a | grep tracker
# Check container logs
docker logs tracker
# Check Docker Compose status
cd /opt/torrust
docker-compose psCommon causes:
- Configuration error in tracker.toml
- Port conflicts (6969, 7070, or 1212 already in use)
- Database file permissions issues
- Invalid database configuration (MySQL connection failed)
Solutions:
-
Fix configuration and restart:
# Edit configuration nano /opt/torrust/config/tracker/tracker.toml # Restart services docker-compose restart tracker
-
Check port availability:
# Check if ports are already in use ss -tulpn | grep -E ':(6969|7070|1212)'
-
Verify database connectivity (if using MySQL):
# Check MySQL container docker ps | grep mysql # Test MySQL connection docker exec mysql mysql -u tracker_user -p -e "SHOW DATABASES;"
Symptoms:
curl http://$VM_IP:7070/announcereturns 404 Not Found- Health check works but announce/scrape don't
Diagnosis:
# Check if HTTP tracker is enabled in config
docker exec tracker cat /etc/torrust/tracker/tracker.toml | grep -A5 "http_trackers"Solutions:
- Ensure
http_trackersarray is not empty in configuration - Verify bind address is
0.0.0.0:7070(not127.0.0.1) - Check firewall rules allow port 7070
Symptoms:
- UDP client times out
- No response from UDP tracker
Diagnosis:
# Check if UDP tracker is enabled
docker exec tracker cat /etc/torrust/tracker/tracker.toml | grep -A5 "udp_trackers"
# Check UDP port is listening
ss -ulpn | grep 6969Solutions:
-
Verify UDP tracker configuration:
# Ensure bind address is 0.0.0.0:6969 docker exec tracker cat /etc/torrust/tracker/tracker.toml
-
Check firewall (UDP port 6969 must be open):
# Check firewall status sudo ufw status # Open UDP port if needed sudo ufw allow 6969/udp
-
Restart tracker:
docker-compose restart tracker
Symptoms:
curl http://$VM_IP:1212/api/v1/stats?token=MyAccessTokenreturns 401 Unauthorized
Diagnosis:
# Check API token in configuration
docker exec tracker cat /etc/torrust/tracker/tracker.toml | grep admin_tokenSolutions:
- Verify token in environment configuration matches tracker.toml
- Ensure token is URL-encoded if it contains special characters
- Token is case-sensitive - verify exact match
Symptoms:
- Announces fail with "missing client IP" error
- Tracker rejects announces without X-Forwarded-For header
Diagnosis:
# Check reverse proxy setting
docker exec tracker cat /etc/torrust/tracker/tracker.toml | grep on_reverse_proxySolutions:
If on_reverse_proxy = true:
# Always include X-Forwarded-For header
curl -H "X-Forwarded-For: 203.0.113.1" \
"http://$VM_IP:7070/announce?..."If not behind a reverse proxy, set on_reverse_proxy = false.
After deployment, verify all tracker functionality:
- Tracker container is running with healthy status
- HTTP tracker health check responds (port 7070)
- HTTP API health check responds (port 1212)
- HTTP announce endpoint accepts requests and returns bencoded response
- HTTP scrape endpoint returns torrent statistics
- REST API
/statsendpoint returns tracker statistics - REST API
/metricsendpoint returns Prometheus metrics - UDP tracker port is listening (port 6969)
- Tracker logs show no errors
- Database connectivity confirmed (if using MySQL)
After successful tracker verification:
- Generate Load Testing: Use torrent clients to generate realistic announce/scrape traffic
- Monitor Performance: Check metrics via Prometheus/Grafana (see prometheus-verification.md and grafana-verification.md)
- Test Database Scaling: If using MySQL, test with larger peer counts (see mysql-verification.md)
- Configure Backup: Set up automated backups for tracker database
- Continue Testing: Return to the Manual E2E Testing Guide for cleanup or additional verification
For troubleshooting common issues during manual testing, see the Troubleshooting section in the main guide.