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>
This commit is contained in:
2026-01-18 11:51:47 -07:00
parent cf4a3ceb26
commit a602118f6d
272 changed files with 37068 additions and 15902 deletions

View File

@@ -0,0 +1,155 @@
//! GuruRMM Server - RMM Management Server
//!
//! Provides the backend API and WebSocket endpoint for GuruRMM agents.
//! Features:
//! - Agent registration and management
//! - Real-time WebSocket communication with agents
//! - Metrics storage and retrieval
//! - Command execution via agents
//! - Dashboard authentication
mod api;
mod auth;
mod config;
mod db;
mod updates;
mod ws;
use std::sync::Arc;
use anyhow::Result;
use axum::{
routing::{get, post},
Router,
};
use sqlx::postgres::PgPoolOptions;
use tokio::sync::RwLock;
use tower_http::cors::{Any, CorsLayer};
use tower_http::trace::TraceLayer;
use tracing::info;
use crate::config::ServerConfig;
use crate::updates::UpdateManager;
use crate::ws::AgentConnections;
/// Shared application state
#[derive(Clone)]
pub struct AppState {
/// Database connection pool
pub db: sqlx::PgPool,
/// Server configuration
pub config: Arc<ServerConfig>,
/// Connected agents (WebSocket connections)
pub agents: Arc<RwLock<AgentConnections>>,
/// Agent update manager
pub updates: Arc<UpdateManager>,
}
#[tokio::main]
async fn main() -> Result<()> {
// Load environment variables from .env file
dotenvy::dotenv().ok();
// Initialize logging
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive("gururmm_server=info".parse()?)
.add_directive("tower_http=debug".parse()?)
.add_directive("info".parse()?),
)
.init();
info!("GuruRMM Server starting...");
// Load configuration
let config = ServerConfig::from_env()?;
info!("Server configuration loaded");
// Connect to database
info!("Connecting to database...");
let db = PgPoolOptions::new()
.max_connections(config.database.max_connections)
.connect(&config.database.url)
.await?;
info!("Database connected");
// Run migrations
info!("Running database migrations...");
sqlx::migrate!("./migrations").run(&db).await?;
info!("Migrations complete");
// Initialize update manager
let update_manager = UpdateManager::new(
config.updates.downloads_dir.clone(),
config.updates.downloads_base_url.clone(),
config.updates.auto_update_enabled,
config.updates.update_timeout_secs,
);
// Initial scan for available versions
info!("Scanning for available agent versions...");
if let Err(e) = update_manager.scan_versions().await {
tracing::warn!("Failed to scan agent versions: {} (continuing without auto-update)", e);
}
let update_manager = Arc::new(update_manager);
// Spawn background scanner (handle is intentionally not awaited - runs until server shutdown)
let _scanner_handle = update_manager.spawn_scanner(config.updates.scan_interval_secs);
info!(
"Auto-update: {} (scan interval: {}s)",
if config.updates.auto_update_enabled { "enabled" } else { "disabled" },
config.updates.scan_interval_secs
);
// Create shared state
let state = AppState {
db,
config: Arc::new(config.clone()),
agents: Arc::new(RwLock::new(AgentConnections::new())),
updates: update_manager,
};
// Build router
let app = build_router(state);
// Start server
let addr = format!("{}:{}", config.server.host, config.server.port);
info!("Starting server on {}", addr);
let listener = tokio::net::TcpListener::bind(&addr).await?;
axum::serve(listener, app).await?;
Ok(())
}
/// Build the application router
fn build_router(state: AppState) -> Router {
// CORS configuration (allow dashboard access)
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any);
Router::new()
// Health check
.route("/health", get(health_check))
// WebSocket endpoint for agents
.route("/ws", get(ws::ws_handler))
// API routes
.nest("/api", api::routes())
// Middleware
.layer(TraceLayer::new_for_http())
.layer(cors)
// State
.with_state(state)
}
/// Health check endpoint
async fn health_check() -> &'static str {
"OK"
}