juicehost/
config.rs

1//! Config loaded from environment variables.
2
3use std::path::PathBuf;
4
5/// Holds every setting juicehost needs to run.
6///
7/// All values come from environment variables with sensible fallbacks.
8/// Check Config::from_env to see what variables are available.
9#[derive(Debug, Clone)]
10pub struct Config {
11    pub public_host: String,
12    pub public_port: u16,
13    pub worker_threads: usize,
14    pub listen_backlog: u32,
15    pub files_dir: PathBuf,
16    pub backend_url: String,
17    pub api_key: String,
18    pub allowed_origins: Vec<String>,
19    pub min_free_space_bytes: u64,
20}
21
22impl Config {
23    /// Load settings from the environment.
24    ///
25    /// Environment variables it reads:
26    /// PUBLIC_HOST (default 127.0.0.1) -- TCP bind address
27    /// PUBLIC_PORT (default 6402) -- TCP bind port, QUIC on UDP 6403
28    /// WORKER_THREADS (default 8) -- Tokio worker threads
29    /// LISTEN_BACKLOG (default 4096) -- TCP listen backlog
30    /// FILES_DIR (default ./files) -- where files are stored
31    /// BACKEND_URL (default http://127.0.0.1:6401) -- juiceback URL
32    /// JUICEHOST_API_KEY -- shared secret for internal API auth
33    /// ALLOWED_ORIGINS (default BACKEND_URL) -- comma separated origin whitelist
34    /// MIN_FREE_SPACE_GB (default 5) -- minimum free disk space
35    pub fn from_env() -> Self {
36        let public_host = std::env::var("PUBLIC_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
37        let public_port = std::env::var("PUBLIC_PORT")
38            .ok()
39            .and_then(|p| p.parse().ok())
40            .unwrap_or(6402);
41        let worker_threads = std::env::var("WORKER_THREADS")
42            .ok()
43            .and_then(|t| t.parse().ok())
44            .unwrap_or(8);
45        let listen_backlog = std::env::var("LISTEN_BACKLOG")
46            .ok()
47            .and_then(|b| b.parse().ok())
48            .unwrap_or(4096);
49        let files_dir = std::env::var("FILES_DIR")
50            .unwrap_or_else(|_| "./files".to_string())
51            .into();
52        let backend_url = std::env::var("BACKEND_URL")
53            .unwrap_or_else(|_| "http://127.0.0.1:6401".to_string())
54            .trim_end_matches('/')
55            .to_string();
56        let api_key = std::env::var("JUICEHOST_API_KEY").unwrap_or_default();
57        let allowed_origins = std::env::var("ALLOWED_ORIGINS")
58            .unwrap_or_else(|_| backend_url.clone())
59            .split(',')
60            .map(|s| s.trim().to_string())
61            .filter(|s| !s.is_empty())
62            .collect();
63
64        let min_free_space_gb = std::env::var("MIN_FREE_SPACE_GB")
65            .ok()
66            .and_then(|v| v.parse::<u64>().ok())
67            .unwrap_or(5);
68        let min_free_space_bytes = min_free_space_gb * 1024 * 1024 * 1024;
69
70        Self {
71            public_host,
72            public_port,
73            worker_threads,
74            listen_backlog,
75            files_dir,
76            backend_url,
77            api_key,
78            allowed_origins,
79            min_free_space_bytes,
80        }
81    }
82}