Files
claudetools/projects/msp-tools/guru-rmm/server/src/config.rs
Mike Swanson 6c316aa701 Add VPN configuration tools and agent documentation
Created comprehensive VPN setup tooling for Peaceful Spirit L2TP/IPsec connection
and enhanced agent documentation framework.

VPN Configuration (PST-NW-VPN):
- Setup-PST-L2TP-VPN.ps1: Automated L2TP/IPsec setup with split-tunnel and DNS
- Connect-PST-VPN.ps1: Connection helper with PPP adapter detection, DNS (192.168.0.2), and route config (192.168.0.0/24)
- Connect-PST-VPN-Standalone.ps1: Self-contained connection script for remote deployment
- Fix-PST-VPN-Auth.ps1: Authentication troubleshooting for CHAP/MSChapv2
- Diagnose-VPN-Interface.ps1: Comprehensive VPN interface and routing diagnostic
- Quick-Test-VPN.ps1: Fast connectivity verification (DNS/router/routes)
- Add-PST-VPN-Route-Manual.ps1: Manual route configuration helper
- vpn-connect.bat, vpn-disconnect.bat: Simple batch file shortcuts
- OpenVPN config files (Windows-compatible, abandoned for L2TP)

Key VPN Implementation Details:
- L2TP creates PPP adapter with connection name as interface description
- UniFi auto-configures DNS (192.168.0.2) but requires manual route to 192.168.0.0/24
- Split-tunnel enabled (only remote traffic through VPN)
- All-user connection for pre-login auto-connect via scheduled task
- Authentication: CHAP + MSChapv2 for UniFi compatibility

Agent Documentation:
- AGENT_QUICK_REFERENCE.md: Quick reference for all specialized agents
- documentation-squire.md: Documentation and task management specialist agent
- Updated all agent markdown files with standardized formatting

Project Organization:
- Moved conversation logs to dedicated directories (guru-connect-conversation-logs, guru-rmm-conversation-logs)
- Cleaned up old session JSONL files from projects/msp-tools/
- Added guru-connect infrastructure (agent, dashboard, proto, scripts, .gitea workflows)
- Added guru-rmm server components and deployment configs

Technical Notes:
- VPN IP pool: 192.168.4.x (client gets 192.168.4.6)
- Remote network: 192.168.0.0/24 (router at 192.168.0.10)
- PSK: rrClvnmUeXEFo90Ol+z7tfsAZHeSK6w7
- Credentials: pst-admin / 24Hearts$

Files: 15 VPN scripts, 2 agent docs, conversation log reorganization,
guru-connect/guru-rmm infrastructure additions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-18 11:51:47 -07:00

162 lines
4.8 KiB
Rust

//! Server configuration
//!
//! Configuration is loaded from environment variables.
//! Required variables:
//! - DATABASE_URL: PostgreSQL connection string
//! - JWT_SECRET: Secret key for JWT token signing
//!
//! Optional variables:
//! - SERVER_HOST: Host to bind to (default: 0.0.0.0)
//! - SERVER_PORT: Port to bind to (default: 3001)
//! - DB_MAX_CONNECTIONS: Max database connections (default: 10)
//! - DOWNLOADS_DIR: Directory containing agent binaries (default: /var/www/downloads)
//! - DOWNLOADS_BASE_URL: Base URL for downloads (default: http://localhost:3001/downloads)
//! - AUTO_UPDATE_ENABLED: Enable automatic agent updates (default: true)
//! - UPDATE_TIMEOUT_SECS: Timeout for agent updates (default: 180)
use std::path::PathBuf;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
/// Root server configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
/// Server binding configuration
pub server: ServerBindConfig,
/// Database configuration
pub database: DatabaseConfig,
/// Authentication configuration
pub auth: AuthConfig,
/// Agent updates configuration
pub updates: UpdatesConfig,
}
/// Server binding configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerBindConfig {
/// Host to bind to
pub host: String,
/// Port to bind to
pub port: u16,
}
/// Database configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseConfig {
/// PostgreSQL connection URL
pub url: String,
/// Maximum number of connections in the pool
pub max_connections: u32,
}
/// Authentication configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthConfig {
/// JWT signing secret
pub jwt_secret: String,
/// JWT token expiry in hours
pub jwt_expiry_hours: u64,
/// API key prefix for agents
pub api_key_prefix: String,
}
/// Agent updates configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdatesConfig {
/// Directory containing agent binaries
pub downloads_dir: PathBuf,
/// Base URL for agent downloads
pub downloads_base_url: String,
/// Enable automatic agent updates
pub auto_update_enabled: bool,
/// Timeout for agent updates in seconds
pub update_timeout_secs: u64,
/// Interval for scanning downloads directory (seconds)
pub scan_interval_secs: u64,
}
impl ServerConfig {
/// Load configuration from environment variables
pub fn from_env() -> Result<Self> {
let database_url =
std::env::var("DATABASE_URL").context("DATABASE_URL environment variable not set")?;
let jwt_secret =
std::env::var("JWT_SECRET").context("JWT_SECRET environment variable not set")?;
let host = std::env::var("SERVER_HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
let port = std::env::var("SERVER_PORT")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(3001);
let max_connections = std::env::var("DB_MAX_CONNECTIONS")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(10);
let jwt_expiry_hours = std::env::var("JWT_EXPIRY_HOURS")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(24);
let api_key_prefix =
std::env::var("API_KEY_PREFIX").unwrap_or_else(|_| "grmm_".to_string());
// Updates configuration
let downloads_dir = std::env::var("DOWNLOADS_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/var/www/downloads"));
let downloads_base_url = std::env::var("DOWNLOADS_BASE_URL")
.unwrap_or_else(|_| format!("http://{}:{}/downloads", host, port));
let auto_update_enabled = std::env::var("AUTO_UPDATE_ENABLED")
.map(|v| v.to_lowercase() == "true" || v == "1")
.unwrap_or(true);
let update_timeout_secs = std::env::var("UPDATE_TIMEOUT_SECS")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(180);
let scan_interval_secs = std::env::var("SCAN_INTERVAL_SECS")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(300); // 5 minutes
Ok(Self {
server: ServerBindConfig { host, port },
database: DatabaseConfig {
url: database_url,
max_connections,
},
auth: AuthConfig {
jwt_secret,
jwt_expiry_hours,
api_key_prefix,
},
updates: UpdatesConfig {
downloads_dir,
downloads_base_url,
auto_update_enabled,
update_timeout_secs,
scan_interval_secs,
},
})
}
}