From 2d7df3da6c194db0a4018b3a3868cd6733a4c6cd Mon Sep 17 00:00:00 2001 From: Dimasssss Date: Sun, 15 Mar 2026 19:06:56 +0300 Subject: [PATCH 1/4] Update FAQ.ru.md --- docs/FAQ.ru.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.ru.md b/docs/FAQ.ru.md index a2fcf1a..cb5db7f 100644 --- a/docs/FAQ.ru.md +++ b/docs/FAQ.ru.md @@ -55,7 +55,10 @@ user2 = "00000000000000000000000000000002" user3 = "00000000000000000000000000000003" ``` 4. Сохранить конфиг. Ctrl+S -> Ctrl+X. Перезапускать telemt не нужно. -5. Получить ссылки через `journalctl -u telemt -n -g "links" --no-pager -o cat | tac` +5. Получить ссылки через +```bash +curl -s http://127.0.0.1:9091/v1/users | jq +``` ## Как посмотреть метрики From 3d5af3d248a9e7be97e95e69a10495271b543a74 Mon Sep 17 00:00:00 2001 From: Dimasssss Date: Sun, 15 Mar 2026 19:09:02 +0300 Subject: [PATCH 2/4] Update FAQ.en.md --- docs/FAQ.en.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.en.md b/docs/FAQ.en.md index 49d1592..e3a6519 100644 --- a/docs/FAQ.en.md +++ b/docs/FAQ.en.md @@ -55,7 +55,10 @@ user2 = "00000000000000000000000000000002" user3 = "00000000000000000000000000000003" ``` 4. Save the config. Ctrl+S -> Ctrl+X. You don't need to restart telemt. -5. Get the links via `journalctl -u telemt -n -g "links" --no-pager -o cat | tac` +5. Get the links via +```bash +curl -s http://127.0.0.1:9091/v1/users | jq +``` ## How to view metrics From 3634fbd7e8e58e631dde54d8906ba28b74642e19 Mon Sep 17 00:00:00 2001 From: Alexey <247128645+axkurcom@users.noreply.github.com> Date: Sun, 15 Mar 2026 23:00:17 +0300 Subject: [PATCH 3/4] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1990109..2102a3a 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ ### 🇷🇺 RU -#### Релиз 3.3.16 +#### Релиз 3.3.15 Semistable -[3.3.16](https://github.com/telemt/telemt/releases/tag/3.3.16)! +[3.3.15](https://github.com/telemt/telemt/releases/tag/3.3.15) по итогам работы в продакшн признан одним из самых стабильных и рекомендуется к использованию, когда cutting-edge фичи некритичны! Будем рады вашему фидбеку и предложениям по улучшению — особенно в части **API**, **статистики**, **UX** @@ -40,9 +40,9 @@ ### 🇬🇧 EN -#### Release 3.3.16 +#### Release 3.3.15 Semistable -[3.3.16](https://github.com/telemt/telemt/releases/tag/3.3.16) +[3.3.15](https://github.com/telemt/telemt/releases/tag/3.3.15) is, based on the results of his work in production, recognized as one of the most stable and recommended for use when cutting-edge features are not so necessary! We are looking forward to your feedback and improvement proposals — especially regarding **API**, **statistics**, **UX** From c351e08c43c40e6b6b4767ae19b35f830e63768d Mon Sep 17 00:00:00 2001 From: Maxim Anisimov Date: Fri, 13 Mar 2026 14:36:28 +0300 Subject: [PATCH 4/4] add support for data path option This commit adds support for configuring the data path via a configuration file or command-line option. This may be useful on systems without systemd, such as OpenWrt or Alpine Linux. Signed-off-by: Maxim Anisimov --- src/config/types.rs | 5 +++++ src/maestro/helpers.rs | 19 +++++++++++++++++-- src/maestro/mod.rs | 30 +++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/config/types.rs b/src/config/types.rs index e523592..04a22ce 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -3,6 +3,7 @@ use ipnetwork::IpNetwork; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::IpAddr; +use std::path::PathBuf; use super::defaults::*; @@ -356,6 +357,9 @@ impl Default for NetworkConfig { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GeneralConfig { + #[serde(default)] + pub data_path: Option, + #[serde(default)] pub modes: ProxyModes, @@ -871,6 +875,7 @@ pub struct GeneralConfig { impl Default for GeneralConfig { fn default() -> Self { Self { + data_path: None, modes: ProxyModes::default(), prefer_ipv6: false, fast_mode: default_true(), diff --git a/src/maestro/helpers.rs b/src/maestro/helpers.rs index acaecdd..78f3ec4 100644 --- a/src/maestro/helpers.rs +++ b/src/maestro/helpers.rs @@ -1,4 +1,5 @@ use std::time::Duration; +use std::path::PathBuf; use tokio::sync::watch; use tracing::{debug, error, info, warn}; @@ -9,8 +10,9 @@ use crate::transport::middle_proxy::{ ProxyConfigData, fetch_proxy_config_with_raw, load_proxy_config_cache, save_proxy_config_cache, }; -pub(crate) fn parse_cli() -> (String, bool, Option) { +pub(crate) fn parse_cli() -> (String, Option, bool, Option) { let mut config_path = "config.toml".to_string(); + let mut data_path: Option = None; let mut silent = false; let mut log_level: Option = None; @@ -28,6 +30,18 @@ pub(crate) fn parse_cli() -> (String, bool, Option) { let mut i = 0; while i < args.len() { match args[i].as_str() { + "--data-path" => { + i += 1; + if i < args.len() { + data_path = Some(PathBuf::from(args[i].clone())); + } else { + eprintln!("Missing value for --data-path"); + std::process::exit(0); + } + } + s if s.starts_with("--data-path=") => { + data_path = Some(PathBuf::from(s.trim_start_matches("--data-path=").to_string())); + } "--silent" | "-s" => { silent = true; } @@ -44,6 +58,7 @@ pub(crate) fn parse_cli() -> (String, bool, Option) { eprintln!("Usage: telemt [config.toml] [OPTIONS]"); eprintln!(); eprintln!("Options:"); + eprintln!(" --data-path Set data directory (absolute path; overrides config value)"); eprintln!(" --silent, -s Suppress info logs"); eprintln!(" --log-level debug|verbose|normal|silent"); eprintln!(" --help, -h Show this help"); @@ -78,7 +93,7 @@ pub(crate) fn parse_cli() -> (String, bool, Option) { i += 1; } - (config_path, silent, log_level) + (config_path, data_path, silent, log_level) } pub(crate) fn print_proxy_links(host: &str, port: u16, config: &ProxyConfig) { diff --git a/src/maestro/mod.rs b/src/maestro/mod.rs index 3db7f02..047c204 100644 --- a/src/maestro/mod.rs +++ b/src/maestro/mod.rs @@ -58,7 +58,7 @@ pub async fn run() -> std::result::Result<(), Box> { startup_tracker .start_component(COMPONENT_CONFIG_LOAD, Some("load and validate config".to_string())) .await; - let (config_path, cli_silent, cli_log_level) = parse_cli(); + let (config_path, data_path, cli_silent, cli_log_level) = parse_cli(); let mut config = match ProxyConfig::load(&config_path) { Ok(c) => c, @@ -80,6 +80,34 @@ pub async fn run() -> std::result::Result<(), Box> { std::process::exit(1); } + if let Some(p) = data_path { + config.general.data_path = Some(p); + } + + if let Some(ref data_path) = config.general.data_path { + if !data_path.is_absolute() { + eprintln!("[telemt] data_path must be absolute: {}", data_path.display()); + std::process::exit(1); + } + + if data_path.exists() { + if !data_path.is_dir() { + eprintln!("[telemt] data_path exists but is not a directory: {}", data_path.display()); + std::process::exit(1); + } + } else { + if let Err(e) = std::fs::create_dir_all(data_path) { + eprintln!("[telemt] Can't create data_path {}: {}", data_path.display(), e); + std::process::exit(1); + } + } + + if let Err(e) = std::env::set_current_dir(data_path) { + eprintln!("[telemt] Can't use data_path {}: {}", data_path.display(), e); + std::process::exit(1); + } + } + if let Err(e) = crate::network::dns_overrides::install_entries(&config.network.dns_overrides) { eprintln!("[telemt] Invalid network.dns_overrides: {}", e); std::process::exit(1);