Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ axum = { version = "0", features = ["macros"] }
axum-client-ip = "0"
axum-extra = { version = "0", features = ["query"] }
axum-server = { version = "0", features = ["tls-rustls"] }
camino = { version = "1.1.6", features = ["serde"] }
chrono = { version = "0", default-features = false, features = ["clock"] }
clap = { version = "4", features = ["derive", "env"] }
crossbeam-skiplist = "0.1"
Expand Down
1 change: 1 addition & 0 deletions cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Buildx",
"byteorder",
"callgrind",
"camino",
"canonicalize",
"canonicalized",
"certbot",
Expand Down
1 change: 1 addition & 0 deletions packages/configuration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version.workspace = true
version.workspace = true

[dependencies]
camino = { version = "1.1.6", features = ["serde"] }
derive_more = "0"
figment = { version = "0.10.18", features = ["env", "test", "toml"] }
serde = { version = "1", features = ["derive"] }
Expand Down
33 changes: 32 additions & 1 deletion packages/configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
//! This module contains the configuration data structures for the
//! Torrust Tracker, which is a `BitTorrent` tracker server.
//!
//! The current version for configuration is [`v1`](crate::v1).
//! The current version for configuration is [`v1`].
pub mod v1;

use std::collections::HashMap;
use std::sync::Arc;
use std::{env, fs};

use camino::Utf8PathBuf;
use derive_more::Constructor;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, NoneAsEmptyString};
use thiserror::Error;
use torrust_tracker_located_error::{DynError, LocatedError};

Expand Down Expand Up @@ -157,3 +160,31 @@ impl From<figment::Error> for Error {
}
}
}

#[serde_as]
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Default)]
pub struct TslConfig {
/// Path to the SSL certificate file.
#[serde_as(as = "NoneAsEmptyString")]
pub ssl_cert_path: Option<Utf8PathBuf>,
/// Path to the SSL key file.
#[serde_as(as = "NoneAsEmptyString")]
pub ssl_key_path: Option<Utf8PathBuf>,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
/// A level lower than all log levels.
Off,
/// Corresponds to the `Error` log level.
Error,
/// Corresponds to the `Warn` log level.
Warn,
/// Corresponds to the `Info` log level.
Info,
/// Corresponds to the `Debug` log level.
Debug,
/// Corresponds to the `Trace` log level.
Trace,
}
88 changes: 88 additions & 0 deletions packages/configuration/src/v1/core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::net::{IpAddr, Ipv4Addr};

use serde::{Deserialize, Serialize};
use torrust_tracker_primitives::{DatabaseDriver, TrackerMode};

use crate::{AnnouncePolicy, LogLevel};

#[allow(clippy::struct_excessive_bools)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct Core {
/// Logging level. Possible values are: `Off`, `Error`, `Warn`, `Info`,
/// `Debug` and `Trace`. Default is `Info`.
pub log_level: Option<LogLevel>,
/// Tracker mode. See [`TrackerMode`] for more information.
pub mode: TrackerMode,

// Database configuration
/// Database driver. Possible values are: `Sqlite3`, and `MySQL`.
pub db_driver: DatabaseDriver,
/// Database connection string. The format depends on the database driver.
/// For `Sqlite3`, the format is `path/to/database.db`, for example:
/// `./storage/tracker/lib/database/sqlite3.db`.
/// For `Mysql`, the format is `mysql://db_user:db_user_password:port/db_name`, for
/// example: `root:password@localhost:3306/torrust`.
pub db_path: String,

/// See [`AnnouncePolicy::interval`]
pub announce_interval: u32,

/// See [`AnnouncePolicy::interval_min`]
pub min_announce_interval: u32,
/// Weather the tracker is behind a reverse proxy or not.
/// If the tracker is behind a reverse proxy, the `X-Forwarded-For` header
/// sent from the proxy will be used to get the client's IP address.
pub on_reverse_proxy: bool,
/// The external IP address of the tracker. If the client is using a
/// loopback IP address, this IP address will be used instead. If the peer
/// is using a loopback IP address, the tracker assumes that the peer is
/// in the same network as the tracker and will use the tracker's IP
/// address instead.
pub external_ip: Option<IpAddr>,
/// Weather the tracker should collect statistics about tracker usage.
/// If enabled, the tracker will collect statistics like the number of
/// connections handled, the number of announce requests handled, etc.
/// Refer to the [`Tracker`](https://docs.rs/torrust-tracker) for more
/// information about the collected metrics.
pub tracker_usage_statistics: bool,
/// If enabled the tracker will persist the number of completed downloads.
/// That's how many times a torrent has been downloaded completely.
pub persistent_torrent_completed_stat: bool,

// Cleanup job configuration
/// Maximum time in seconds that a peer can be inactive before being
/// considered an inactive peer. If a peer is inactive for more than this
/// time, it will be removed from the torrent peer list.
pub max_peer_timeout: u32,
/// Interval in seconds that the cleanup job will run to remove inactive
/// peers from the torrent peer list.
pub inactive_peer_cleanup_interval: u64,
/// If enabled, the tracker will remove torrents that have no peers.
/// The clean up torrent job runs every `inactive_peer_cleanup_interval`
/// seconds and it removes inactive peers. Eventually, the peer list of a
/// torrent could be empty and the torrent will be removed if this option is
/// enabled.
pub remove_peerless_torrents: bool,
}

impl Default for Core {
fn default() -> Self {
let announce_policy = AnnouncePolicy::default();

Self {
log_level: Some(LogLevel::Info),
mode: TrackerMode::Public,
db_driver: DatabaseDriver::Sqlite3,
db_path: String::from("./storage/tracker/lib/database/sqlite3.db"),
announce_interval: announce_policy.interval,
min_announce_interval: announce_policy.interval_min,
max_peer_timeout: 900,
on_reverse_proxy: false,
external_ip: Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))),
tracker_usage_statistics: true,
persistent_torrent_completed_stat: false,
inactive_peer_cleanup_interval: 600,
remove_peerless_torrents: true,
}
}
}
6 changes: 4 additions & 2 deletions packages/configuration/src/v1/health_check_api.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use serde::{Deserialize, Serialize};
use serde_with::serde_as;

Expand All @@ -9,13 +11,13 @@ pub struct HealthCheckApi {
/// The format is `ip:port`, for example `127.0.0.1:1313`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
pub bind_address: String,
pub bind_address: SocketAddr,
}

impl Default for HealthCheckApi {
fn default() -> Self {
Self {
bind_address: String::from("127.0.0.1:1313"),
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1313),
}
}
}
22 changes: 11 additions & 11 deletions packages/configuration/src/v1/http_tracker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use serde::{Deserialize, Serialize};
use serde_with::{serde_as, NoneAsEmptyString};
use serde_with::serde_as;

use crate::TslConfig;

/// Configuration for each HTTP tracker.
#[serde_as]
Expand All @@ -11,25 +15,21 @@ pub struct HttpTracker {
/// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to
/// listen to all interfaces, use `0.0.0.0`. If you want the operating
/// system to choose a random port, use port `0`.
pub bind_address: String,
pub bind_address: SocketAddr,
/// Weather the HTTP tracker will use SSL or not.
pub ssl_enabled: bool,
/// Path to the SSL certificate file. Only used if `ssl_enabled` is `true`.
#[serde_as(as = "NoneAsEmptyString")]
pub ssl_cert_path: Option<String>,
/// Path to the SSL key file. Only used if `ssl_enabled` is `true`.
#[serde_as(as = "NoneAsEmptyString")]
pub ssl_key_path: Option<String>,
/// TSL config. Only used if `ssl_enabled` is true.
#[serde(flatten)]
pub tsl_config: TslConfig,
}

impl Default for HttpTracker {
fn default() -> Self {
Self {
enabled: false,
bind_address: String::from("0.0.0.0:7070"),
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 7070),
ssl_enabled: false,
ssl_cert_path: None,
ssl_key_path: None,
tsl_config: TslConfig::default(),
}
}
}
Loading