rush_sync_server/setup/
setup_toml.rs1use crate::core::prelude::*;
3use std::path::PathBuf;
4use tokio::fs;
5
6const DEFAULT_CONFIG: &str = r#"[general]
8max_messages = 1000
9typewriter_delay = 5
10input_max_length = 100
11max_history = 30
12poll_rate = 16
13log_level = "info"
14current_theme = "dark"
15
16[language]
17current = "en"
18
19# =====================================================
20# SERVER CONFIGURATION
21# =====================================================
22[server]
23# Port Management
24port_range_start = 8000 # Starting port for auto-allocation
25port_range_end = 8200 # Maximum port for auto-allocation
26max_concurrent = 50 # Maximum simultaneous servers
27shutdown_timeout = 5 # Graceful shutdown timeout (seconds)
28startup_delay_ms = 500 # Delay after server creation (milliseconds)
29workers = 1 # Actix workers per server
30auto_open_browser = true # Automatically open browser
31bind_address = "127.0.0.1" # Server bind address ("0.0.0.0" for public access)
32
33# HTTPS/TLS Configuration
34enable_https = true # Enable HTTPS support
35https_port_offset = 1000 # HTTPS port = HTTP port + offset
36cert_dir = ".rss/certs" # Certificate storage directory
37auto_cert = true # Generate certificates automatically
38cert_validity_days = 365 # Certificate validity (days)
39
40# Production Settings
41use_lets_encrypt = false # Use Let's Encrypt (requires public domain)
42production_domain = "localhost" # Production domain name
43acme_email = "" # Email for Let's Encrypt notifications (optional)
44
45# Security: plaintext, hash ($hmac-sha256$...), or RSS_API_KEY env var
46# Generate hash: rush-sync --hash-key <your-key>
47api_key = "" # API key for /api/*, /.rss/*, /ws/* endpoints (empty = no auth)
48
49# Rate Limiting
50rate_limit_rps = 100 # Max requests per second per IP for /api/* endpoints
51rate_limit_enabled = true # Enable rate limiting
52
53# =====================================================
54# REVERSE PROXY CONFIGURATION
55# =====================================================
56[proxy]
57enabled = true # Enable integrated reverse proxy
58port = 3000 # Proxy listening port
59https_port_offset = 443 # Added for HTTPS offset
60bind_address = "127.0.0.1" # Proxy bind address
61health_check_interval = 30 # Health check interval (seconds)
62timeout_ms = 5000 # Request timeout (milliseconds)
63
64# For production use:
65# port = 80 # Standard HTTP Port
66# bind_address = "0.0.0.0" # All interfaces (for external access)
67
68# =====================================================
69# LOGGING CONFIGURATION
70# =====================================================
71[logging]
72max_file_size_mb = 100 # Log rotation size (100MB per file)
73max_archive_files = 9 # Archive generations (9 backups)
74compress_archives = true # GZIP compression for archives
75log_requests = true # Enable request logging
76log_security_alerts = true # Enable security monitoring
77log_performance = true # Enable performance metrics
78
79# =====================================================
80# THEME DEFINITIONS
81# =====================================================
82[theme.dark]
83output_bg = "Black"
84output_text = "White"
85output_cursor = "PIPE"
86output_cursor_color = "White"
87input_bg = "White"
88input_text = "Black"
89input_cursor_prefix = "/// "
90input_cursor = "PIPE"
91input_cursor_color = "Black"
92
93[theme.light]
94output_bg = "White"
95output_text = "Black"
96output_cursor = "PIPE"
97output_cursor_color = "Black"
98input_bg = "Black"
99input_text = "White"
100input_cursor_prefix = "/// "
101input_cursor = "PIPE"
102input_cursor_color = "White"
103
104[theme.green]
105output_bg = "Black"
106output_text = "Green"
107output_cursor = "BLOCK"
108output_cursor_color = "Green"
109input_bg = "LightGreen"
110input_text = "Black"
111input_cursor_prefix = "$ "
112input_cursor = "BLOCK"
113input_cursor_color = "Black"
114
115[theme.blue]
116output_bg = "White"
117output_text = "LightBlue"
118output_cursor = "UNDERSCORE"
119output_cursor_color = "Blue"
120input_bg = "Blue"
121input_text = "White"
122input_cursor_prefix = "> "
123input_cursor = "UNDERSCORE"
124input_cursor_color = "White"
125"#;
126
127pub async fn ensure_config_exists() -> Result<PathBuf> {
128 let config_path = get_primary_config_path()?;
129
130 if let Some(parent) = config_path.parent() {
132 fs::create_dir_all(parent).await.map_err(AppError::Io)?;
133 }
134
135 if !config_path.exists() {
137 fs::write(&config_path, DEFAULT_CONFIG)
138 .await
139 .map_err(AppError::Io)?;
140
141 log::info!(
142 "{}",
143 get_translation(
144 "system.config.file_created",
145 &[&config_path.display().to_string()]
146 )
147 );
148 }
149
150 Ok(config_path)
151}
152
153pub fn get_config_paths() -> Vec<PathBuf> {
154 let mut paths = Vec::new();
155
156 if let Ok(exe_path) = std::env::current_exe() {
157 if let Some(base_dir) = exe_path.parent() {
158 paths.push(base_dir.join(".rss/rush.toml"));
160 paths.push(base_dir.join("rush.toml"));
161 paths.push(base_dir.join("config/rush.toml"));
162 }
163 }
164
165 #[cfg(debug_assertions)]
167 {
168 paths.push(PathBuf::from("rush.toml"));
169 paths.push(PathBuf::from("src/rush.toml"));
170 }
171
172 paths
173}
174
175fn get_primary_config_path() -> Result<PathBuf> {
176 let exe_path = std::env::current_exe().map_err(AppError::Io)?;
177 let base_dir = exe_path
178 .parent()
179 .ok_or_else(|| AppError::Validation(get_translation("system.config.dir_error", &[])))?;
180
181 Ok(base_dir.join(".rss/rush.toml"))
182}