diff --git a/agent/src/collectors/service.rs b/agent/src/collectors/service.rs index 80748ea..f051fe5 100644 --- a/agent/src/collectors/service.rs +++ b/agent/src/collectors/service.rs @@ -622,70 +622,42 @@ impl ServiceCollector { } async fn get_nginx_sites(&self) -> Option> { - // Check enabled sites in sites-enabled directory - let sites_enabled_dir = "/etc/nginx/sites-enabled"; - - let mut entries = match fs::read_dir(sites_enabled_dir).await { - Ok(entries) => entries, - Err(_) => return None, - }; + // For NixOS and other systems, get the actual running nginx config + let output = Command::new("nginx") + .args(["-T"]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .await + .ok()?; + if !output.status.success() { + return None; + } + + let config = String::from_utf8_lossy(&output.stdout); let mut sites = Vec::new(); - while let Ok(Some(entry)) = entries.next_entry().await { - let path = entry.path(); - - // Skip if it's not a file or is a symlink to default - if !path.is_file() { - continue; - } - - let filename = path.file_name()?.to_string_lossy(); - - // Skip default site unless it's the only one - if filename == "default" { - continue; - } - - // Try to extract server names from the config file - if let Ok(config_content) = fs::read_to_string(&path).await { - let mut server_names = Vec::new(); - - for line in config_content.lines() { - let trimmed = line.trim(); - if trimmed.starts_with("server_name") { - // Extract server names from "server_name example.com www.example.com;" - if let Some(names_part) = trimmed.strip_prefix("server_name") { - let names_clean = names_part.trim().trim_end_matches(';'); - for name in names_clean.split_whitespace() { - if name != "_" && !name.is_empty() { - server_names.push(name.to_string()); - break; // Only take the first valid server name - } - } + for line in config.lines() { + let trimmed = line.trim(); + if trimmed.starts_with("server_name") { + // Extract server names from "server_name example.com www.example.com;" + if let Some(names_part) = trimmed.strip_prefix("server_name") { + let names_clean = names_part.trim().trim_end_matches(';'); + for name in names_clean.split_whitespace() { + // Skip default catch-all server names + if name != "_" && !name.is_empty() && name.contains('.') && !name.starts_with('$') { + sites.push(name.to_string()); } } } - - if !server_names.is_empty() { - sites.push(server_names[0].clone()); - } else { - // Fallback to filename if no server_name found - sites.push(filename.to_string()); - } - } else { - // Fallback to filename if can't read config - sites.push(filename.to_string()); } } - // If no sites found, check for default - if sites.is_empty() { - let default_path = format!("{}/default", sites_enabled_dir); - if fs::metadata(&default_path).await.is_ok() { - sites.push("default".to_string()); - } - } + // Remove duplicates and limit to reasonable number + sites.sort(); + sites.dedup(); + sites.truncate(15); // Show max 15 sites to avoid overwhelming the UI if sites.is_empty() { None