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 b0a68d89bf
commit 6c316aa701
272 changed files with 37068 additions and 2 deletions

View File

@@ -0,0 +1,141 @@
import { useQuery } from "@tanstack/react-query";
import { Activity, Server, AlertTriangle, CheckCircle } from "lucide-react";
import { agentsApi, Agent } from "../api/client";
import { Card, CardHeader, CardTitle, CardContent } from "../components/Card";
function StatCard({
title,
value,
icon: Icon,
description,
}: {
title: string;
value: string | number;
icon: React.ComponentType<{ className?: string }>;
description?: string;
}) {
return (
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">{title}</CardTitle>
<Icon className="h-4 w-4 text-[hsl(var(--muted-foreground))]" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{value}</div>
{description && (
<p className="text-xs text-[hsl(var(--muted-foreground))]">{description}</p>
)}
</CardContent>
</Card>
);
}
export function Dashboard() {
const { data: agents = [], isLoading } = useQuery({
queryKey: ["agents"],
queryFn: () => agentsApi.list().then((res) => res.data),
refetchInterval: 30000,
});
const onlineAgents = agents.filter((a: Agent) => a.status === "online");
const offlineAgents = agents.filter((a: Agent) => a.status === "offline");
const errorAgents = agents.filter((a: Agent) => a.status === "error");
return (
<div className="space-y-6">
<div>
<h1 className="text-3xl font-bold">Dashboard</h1>
<p className="text-[hsl(var(--muted-foreground))]">
Overview of your managed endpoints
</p>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<StatCard
title="Total Agents"
value={isLoading ? "..." : agents.length}
icon={Server}
description="Registered endpoints"
/>
<StatCard
title="Online"
value={isLoading ? "..." : onlineAgents.length}
icon={CheckCircle}
description="Currently connected"
/>
<StatCard
title="Offline"
value={isLoading ? "..." : offlineAgents.length}
icon={Activity}
description="Not responding"
/>
<StatCard
title="Errors"
value={isLoading ? "..." : errorAgents.length}
icon={AlertTriangle}
description="Requires attention"
/>
</div>
<div className="grid gap-4 md:grid-cols-2">
<Card>
<CardHeader>
<CardTitle>Recent Activity</CardTitle>
</CardHeader>
<CardContent>
{isLoading ? (
<p className="text-[hsl(var(--muted-foreground))]">Loading...</p>
) : agents.length === 0 ? (
<p className="text-[hsl(var(--muted-foreground))]">
No agents registered yet. Deploy an agent to get started.
</p>
) : (
<div className="space-y-4">
{agents.slice(0, 5).map((agent: Agent) => (
<div key={agent.id} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div
className={`h-2 w-2 rounded-full ${
agent.status === "online"
? "bg-green-500"
: agent.status === "error"
? "bg-red-500"
: "bg-gray-400"
}`}
/>
<div>
<p className="font-medium">{agent.hostname}</p>
<p className="text-xs text-[hsl(var(--muted-foreground))]">
{agent.os_type}
</p>
</div>
</div>
<span className="text-xs text-[hsl(var(--muted-foreground))]">
{agent.last_seen
? new Date(agent.last_seen).toLocaleString()
: "Never seen"}
</span>
</div>
))}
</div>
)}
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Quick Actions</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2 text-sm text-[hsl(var(--muted-foreground))]">
<p>Deploy a new agent to start monitoring endpoints.</p>
<p className="mt-4">
Use the Agents page to view details and send commands to your endpoints.
</p>
</div>
</CardContent>
</Card>
</div>
</div>
);
}