Skip to main content

freshblu_server/
config.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct ServerConfig {
5    /// HTTP port
6    pub http_port: u16,
7    /// MQTT port
8    pub mqtt_port: u16,
9    /// Database URL (sqlite:freshblu.db or postgresql://...)
10    pub database_url: String,
11    /// Bcrypt pepper for extra token security
12    pub pepper: String,
13    /// Open registration (no auth required to register)
14    pub open_registration: bool,
15    /// Max message size in bytes
16    pub max_message_size: usize,
17    /// Log level
18    pub log_level: String,
19    /// NATS URL (if set, use NatsBus; otherwise LocalBus)
20    pub nats_url: Option<String>,
21    /// Redis URL (if set, enable cache layer and presence)
22    pub redis_url: Option<String>,
23    /// Pod ID for NATS delivery routing (defaults to hostname)
24    pub pod_id: String,
25}
26
27impl Default for ServerConfig {
28    fn default() -> Self {
29        Self {
30            http_port: 3000,
31            mqtt_port: 1883,
32            database_url: "sqlite:freshblu.db".to_string(),
33            pepper: "change-me-in-production".to_string(),
34            open_registration: true,
35            max_message_size: 1_048_576, // 1MB
36            log_level: "info".to_string(),
37            nats_url: None,
38            redis_url: None,
39            pod_id: gethostname(),
40        }
41    }
42}
43
44impl ServerConfig {
45    pub fn from_env() -> Self {
46        let _ = dotenvy::dotenv();
47        Self {
48            http_port: std::env::var("FRESHBLU_HTTP_PORT")
49                .ok()
50                .and_then(|v| v.parse().ok())
51                .unwrap_or(3000),
52            mqtt_port: std::env::var("FRESHBLU_MQTT_PORT")
53                .ok()
54                .and_then(|v| v.parse().ok())
55                .unwrap_or(1883),
56            database_url: std::env::var("DATABASE_URL")
57                .unwrap_or_else(|_| "sqlite:freshblu.db".to_string()),
58            pepper: std::env::var("FRESHBLU_PEPPER")
59                .unwrap_or_else(|_| "change-me-in-production".to_string()),
60            open_registration: std::env::var("FRESHBLU_OPEN_REGISTRATION")
61                .map(|v| v != "false")
62                .unwrap_or(true),
63            max_message_size: std::env::var("FRESHBLU_MAX_MESSAGE_SIZE")
64                .ok()
65                .and_then(|v| v.parse().ok())
66                .unwrap_or(1_048_576),
67            log_level: std::env::var("RUST_LOG")
68                .unwrap_or_else(|_| "info".to_string()),
69            nats_url: std::env::var("NATS_URL").ok(),
70            redis_url: std::env::var("REDIS_URL").ok(),
71            pod_id: std::env::var("POD_ID").unwrap_or_else(|_| gethostname()),
72        }
73    }
74}
75
76fn gethostname() -> String {
77    std::env::var("HOSTNAME").unwrap_or_else(|_| {
78        uuid::Uuid::new_v4().to_string()[..8].to_string()
79    })
80}