This repository serves as the backend for the Torrust Index project.
Torrust Index
[![containerwfb]][containerwf] [![coveragewfb]][coveragewf] [![deploymentwfb]][deploymentwf] [![testingwfb]][testingwf] [![labelswfb]][labels_wf]
Torrust Index is a library for [BitTorrent][bittorrent] Files. Written in [Rust Language][rust] (edition 2024, MSRV 1.88) with the [Axum] web framework. This index aims to be respectful to established standards, (both [formal][BEP 00] and [otherwise][torrentsourcefield]).
This is a [Torrust][torrust] project and is in active development. It is community supported as well as sponsored by [Nautilus Cyberneering][nautilus].
About
The core purpose of a [BitTorrent][bittorrent] Index is to maintain a database that connects torrent files with useful metadata. Allowing a community of users to keep track of their torrents in a well-organized and informative manner.
The Torrust Index serves as a [high-level API][API] for our [Torrust Index GUI][gui] client. It also connects to the [management api][api_tracker] of our [Torrust Tracker][tracker], to provide statistics and whitelisting functionality.

Key Features
- [x] High Quality and Modern Rust Codebase.
- [x] [Documentation][docs] Generated from Code Comments.
- [x] [Comprehensive Suite][coverage] of Unit and Functional Tests.
- [x] Good Performance in Busy Conditions.
- [x] Native
IPv4andIPv6support. - [x] Persistent
SQLite3orMySQLDatabases.
Getting Started
Upgrading
If you are using Version 1 of torrust-tracker-backend, please view our [upgrading guide][upgrade.md].
Container Version
The Torrust Index is [deployed to DockerHub][dockerhub], you can run a demo immediately with the following commands. Per ADR-T-009 ยงD2, the image no longer ships a default tracker token or database.connect_url, so two overrides are mandatory at startup โ a bare docker run -it torrust/index:develop now fails with a missing field error rather than booting against hidden defaults.
Docker
docker run -it \
--env TORRUSTINDEXC \
--env TORRUSTINDEXC \
torrust/index:develop
Please read our [container guide][containers.md] for more information.
Podman
podman run -it \
--env TORRUSTINDEXC \
--env TORRUSTINDEXC \
torrust/index:develop
Please read our [container guide][containers.md] for more information.
Compose (development sandbox)
For a complete local stack (index + tracker + MySQL + mailcatcher) the repository ships a Compose split: a production-shaped compose.yaml baseline plus an auto-loaded compose.override.yaml that supplies dev defaults. Two Makefile wrappers cover the documented invocation paths:
# Dev sandbox (auto-loads compose.override.yaml):
make up-dev
Production-shaped (validates required credentials first):
make up-prod
See Compose Split in the container guide for the required env vars and the validation contract.
Development Version
- Please assure you have the [latest stable (or nightly) version of Rust][Rust].
- Please assure that your computer has enough RAM. Recommended 16GB.
Checkout, Test and Run:
# Checkout repository into a new folder:
git clone https://github.com/torrust/torrust-index.git
Change into directory and create a empty database file:
cd torrust-index
mkdir -p ./storage/index/lib/database/
touch ./storage/index/lib/database/sqlite3.db
Check all tests in application:
cargo test --tests --benches --examples --workspace --all-targets --all-features
Run the index:
cargo run
Customization
# Copy the default configuration into the standard location:
mkdir -p ./storage/index/etc/
cp ./share/default/config/index.development.sqlite3.toml ./storage/index/etc/index.toml
Customize the index configuration (for example):
vim ./storage/index/etc/index.toml
Run the index with the updated configuration:
TORRUSTINDEXC cargo run
Optionally, you may choose to supply the entire configuration as an environmental variable:
# Use a configuration supplied on an environmental variable:
TORRUSTINDEXCONFIG_TOML=$(cat "./storage/index/etc/index.toml") cargo run
For deployment, you should override the tracker.token (per ADR-T-009 ยงD2 it is mandatory; the shipped TOMLs no longer carry a default):
# Override secrets in configuration using environmental variables
TORRUSTINDEXCONFIG_TOML=$(cat "./storage/index/etc/index.toml") \
TORRUSTINDEXCONFIGOVERRIDETRACKER_TOKEN=$(cat "./storage/tracker/lib/trackerapiadmintoken.secret") \
cargo run
_By default, an ephemeral RSA key pair is auto-generated in memory for JWT signing. Sessions will not survive server restarts. For persistent sessions, generate your own RSA key pair and configure the paths:_
# Generate an RSA key pair for JWT signing:
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
Supply key paths via environment variables:
TORRUSTINDEXCONFIG_TOML=$(cat "./storage/index/etc/index.toml") \
TORRUSTINDEXC \
TORRUSTINDEXC \
cargo run
Container deployments auto-generate persistent keys on first boot โ no
manual setup is required. See the [container guide][containers.md] for details.
Please view our [crate documentation][docs] for more detailed instructions.
Services
The following services are provided by the default configuration:
- API
http://127.0.0.1:3001/.
Command-Line Output
First-party Torrust Index command-line entrypoints are governed by ADR-T-010: stdout is reserved for machine-readable result data, stderr is reserved for machine-readable diagnostics/control records, and commands that emit stdout result data refuse to write it directly to a terminal.
The torrust-index server binary is a no-stdout command. Application tracing is emitted as JSON records on stderr; the configured [logging].threshold selects the default filter, and a non-empty RUST_LOG environment variable overrides that default. Panics that cross the binary boundary are reported as ADR-T-010 JSON control-plane records on stderr.
Command-reachable server libraries use the same diagnostic path. Shutdown grace-period notices are structured tracing records, and mail-template initialization or rendering failures are propagated to callers for JSON diagnostic reporting instead of being printed or exiting from the mailer library.
The shared helper infrastructure now wraps clap help, version, and usage errors as JSON control-plane records on stderr, installs a JSON-only panic hook, and uses JSON tracing on stderr. The container helper binaries emit exactly one JSON object on stdout when successful, include a top-level schema field, and should be inspected through a pipe or redirect:
torrust-index-auth-keypair | jq .
torrust-index-config-probe | jq .
torrust-index-health-check http://127.0.0.1:3001/health_check | jq .
For helper diagnostics, a non-empty RUST_LOG environment variable takes precedence over --debug; otherwise --debug raises the default diagnostic filter to debug.
The container entry script is also a no-stdout orchestration command. It captures helper stdout internally, keeps its own stdout empty before su-exec, and emits startup validation failures, status records, utility failures, and DEBUG=1 phase diagnostics as JSON records on stderr. Use docker logs ... 2>&1 or your runtime's stderr capture and parse those lines as NDJSON when automation needs startup diagnostics.
Two root diagnostic commands have also been migrated. parse_torrent is a stdout-result command: it emits one JSON object containing schema, torrent, originalv1infohash, and inputbyte_length, and it refuses direct terminal stdout. Pipe or redirect it before inspection:
fixture=./tests/fixtures/torrents/6c690018c5786dbbb00161f62b0712d69296df97withcustominfodict_key.torrent
cargo run --quiet --bin parse_torrent -- "$fixture" | jq .
createtesttorrent is a no-stdout side-effect command. It writes the torrent file into an existing destination directory, keeps stdout empty, and emits JSON status or diagnostic records on stderr:
mkdir -p ./output/test/torrents
cargo run --quiet --bin createtesttorrent -- ./output/test/torrents 2>create-test-torrent.ndjson
jq . create-test-torrent.ndjson
The root maintenance binaries importtrackerstatistics, seeder, and upgrade are no-stdout side-effect commands. They keep stdout empty, use the shared JSON clap wrapper for help, version, and argv errors, and emit status or diagnostic records as JSON/NDJSON on stderr. Automation should branch on the process exit code and parse stderr as JSON when it needs diagnostics:
cargo run --quiet --bin importtrackerstatistics -- 2>import-tracker-statistics.ndjson
cargo run --quiet --bin seeder -- \ --api-base-url "http://localhost:3001" \ --number-of-torrents 10 \ --user admin \ --password "$TORRUSTINDEXADMIN_PASSWORD" \ --interval 0 \ 2>seeder.ndjson
cargo run --quiet --bin upgrade -- ./data.db ./data_v2.db ./uploads 2>upgrade.ndjson jq . upgrade.ndjson
Documentation
- [API (Version 1)][api]
Architecture Decision Records
- ADR-T-001: Lowercase Infohashes โ All infohashes are normalized to lowercase throughout the codebase, database, and API.
- ADR-T-002: Ignore Non-Standard Fields in Info Dictionary โ Non-standard fields in the torrent info dictionary are ignored to prevent info-hash mismatches.
- ADR-T-003: Preparing for Rust Edition 2024 โ Pin dependencies to avoid edition-2024-only crates while the workspace remains on edition 2021; raise MSRV to 1.83.
- ADR-T-004: Remove
located-errorPackage โ Replace thetorrust-index-located-errorwrapper withtracingfor error context. - ADR-T-005: Migrate to Rust Edition 2024 โ Migrate the entire workspace to
edition = "2024"and raise the MSRV to 1.88. - ADR-T-006: Refactor the Error System โ Replace the 41-variant
ServiceErrorgod enum with domain-scoped error enums (AuthError,UserError,TorrentError,CategoryTagError) and a thinApiErrorwrapper. - ADR-T-007: Refactor the JWT System โ Centralise JWT handling into
src/jwt.rs, redesign claims to RFC 7519, move to RS256 asymmetric signing, and consolidate session validation into a single code path. - ADR-T-008: Refactor the Roles and Permissions System โ Replace Casbin with a native Rust permission system (
PermissionMatrix+RequirePermission<A>Axum extractors), migrate fromadministrator: boolto arolecolumn, and add a/me/permissionsdiscovery endpoint. - ADR-T-009: Container Infrastructure Refactor โ Split the runtime image into
release(distroless, root-only toolset) anddebugbases; extract three helper binaries (torrust-index-health-check,torrust-index-auth-keypair,torrust-index-config-probe) into their own workspace crates with no HTTP/TLS/async-runtime deps; strip credentials from shipped TOMLs and makedatabase.connecturl/tracker.tokenmandatory schema fields; split Compose into a production-shapedcompose.yamlbaseline plus an auto-loadedcompose.override.yamldev sandbox; and add an internal audit record for vendoredsu-exec. - ADR-T-010: Global Command-Line Output Contract โ Apply the JSON-only stdout/stderr contract across first-party command-line entrypoints: stdout is result JSON, stderr is diagnostic JSON/NDJSON, and commands with stdout result data refuse direct TTY output.
Contributing
We are happy to support and welcome new people to our project. Please consider our [contributor guide][guide.md].
This is an open-source community-supported project. We welcome contributions from the community!
How can you contribute?
- Bug reports and feature requests.
- Code contributions. You can start by looking at the issues labeled "[good first issues]".
- Documentation improvements. Check the [documentation][docs] and [API documentation][API] for typos, errors, or missing information.
- Participation in the community. You can help by answering questions in the [discussions].
License
Copyright (c) 2023 The Torrust Developers.
This program is free software: you can redistribute it and/or modify it under the terms of the [GNU Affero General Public License][AGPL30] as published by the [Free Software Foundation][FSF], version 3.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [GNU Affero General Public License][AGPL30] for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see
Some files include explicit copyright notices and/or license notices.
Legacy Exception
For posterity, versions of Torrust Index that are older than five years are automatically granted the [MIT-0][MIT0] license in addition to the existing [AGPL-3.0-only][AGPL3_0] license.
Contributor Agreement
The copyright of the Torrust Index is retained by the respective authors.
Contributors agree that:
- All their contributions be granted a license(s) compatible with the Torrust Index License.
- All contributors signal clearly and explicitly any other compatible licenses if they are not: AGPL-3.0-only with the legacy MIT-0 exception.
We kindly ask you to take time and consider The Torrust Project [Contributor Agreement][agreement.md] in full.
Acknowledgments
This project was a joint effort by [Nautilus Cyberneering GmbH][nautilus] and [Dutch Bits].
[container_wf]: ../../actions/workflows/container.yaml [containerwfb]: ../../actions/workflows/container.yaml/badge.svg [coverage_wf]: ../../actions/workflows/coverage.yaml [coveragewfb]: ../../actions/workflows/coverage.yaml/badge.svg [deployment_wf]: ../../actions/workflows/deployment.yaml [deploymentwfb]: ../../actions/workflows/deployment.yaml/badge.svg [testing_wf]: ../../actions/workflows/testing.yaml [testingwfb]: ../../actions/workflows/testing.yaml/badge.svg [labels_wf]: ../../actions/workflows/labels.yaml [labelswfb]: ../../actions/workflows/labels.yaml/badge.svg
[bittorrent]: http://bittorrent.org/ [rust]: https://www.rust-lang.org/ [axum]: https://github.com/tokio-rs/axum [coverage]: https://app.codecov.io/gh/torrust/torrust-index [torrust]: https://torrust.com/
[tracker]: https://github.com/torrust/torrust-tracker [gui]: https://github.com/torrust/torrust-index-gui
[dockerhub]: https://hub.docker.com/r/torrust/index/tags
[torrentsourcefield]: https://github.com/qbittorrent/qBittorrent/discussions/19406
[BEP 00]: https://www.bittorrent.org/beps/bep_0000.html
[containers.md]: ./docs/containers.md [upgrade.md]: ./upgrades/fromv100tov20_0/README.md
[docs]: https://docs.rs/torrust-index/latest/torrust_index/ [api]: https://docs.rs/torrust-index/latest/torrust_index/web/api/v1/ [apitracker]: https://docs.rs/torrust-tracker/latest/torrusttracker/servers/apis/v1
[good first issues]: https://github.com/torrust/torrust-index/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22 [discussions]: https://github.com/torrust/torrust-index/discussions
[guide.md]: https://github.com/torrust/.github/blob/main/info/contributing.md [agreement.md]: https://github.com/torrust/.github/blob/main/info/licensing/contributoragreementv01.md
[AGPL30]: ./docs/licenses/LICENSE-AGPL30 [MIT0]: ./docs/licenses/LICENSE-MIT0 [FSF]: https://www.fsf.org/
[nautilus]: https://github.com/orgs/Nautilus-Cyberneering/ [Dutch Bits]: https://dutchbits.nl