Pulse: Real-time Proxmox Infrastructure Monitoring with Go and TypeScript

┌─────────────────────────────────────────────────────┐
│ Analysis Summary                                    │
├─────────────────────────────────────────────────────┤
│ Type: Project                                       │
│ Primary Language: go + typescript + markdown        │
│ LOC: 95K                                            │
│ Test Files: 15                                      │
│ Architecture: go                                    │
│ Confidence: High                                    │
└─────────────────────────────────────────────────────┘

Analyzed: 2393fff0 from 2025-10-08

Pulse: Real-time Proxmox Infrastructure Monitoring with Go and TypeScript

Pulse provides real-time monitoring for Proxmox VE and Proxmox Backup Server (PBS) environments through a web-based dashboard. The project combines a Go backend for system integration with a modern TypeScript frontend, offering features like auto-discovery of Proxmox nodes, unified backup management, and configurable alerting via email and webhooks.

The codebase spans 94,998 lines across 275 files, with Go handling the backend infrastructure (46,781 lines) and TypeScript powering the frontend interface (37,018 lines). The architecture supports cluster monitoring, Docker container tracking via lightweight agents, and enterprise-grade security features including credential encryption and comprehensive audit logging.

Quick Start

# Recommended: Official installer (auto-detects Proxmox and creates container)
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash

# Alternative: Docker
docker run -d -p 7655:7655 -v pulse_data:/data rcourtman/pulse:latest

Time to first result: ~5 minutes (includes Proxmox node discovery and initial data collection)

Alternative Approaches

Solution Setup Time Learning Curve Scalability Community Support
Pulse ~5 minutes Low Medium Growing
Zabbix ~30 minutes High High Large
Prometheus + Grafana ~45 minutes High Very High Very Large
PRTG ~15 minutes Medium High Commercial
LibreNMS ~20 minutes Medium High Medium

Architecture and Implementation

The project employs a hub-and-spoke WebSocket architecture for real-time updates. The WebSocket hub implementation in internal/websocket/hub_concurrency_test.go:9-28 demonstrates concurrent client management:

func TestHubConcurrentClients(t *testing.T) {
	hub := NewHub(nil)

	// Start hub processing loop in background
	go hub.Run()

	const iterations = 200

	var wg sync.WaitGroup
	wg.Add(3)

	// Simulate register/unregister from multiple goroutines
	go func() {
		defer wg.Done()
		for i := 0; i < iterations; i++ {
			client := &Client{
				hub:  hub,
				send: make(chan []byte, 10),
				id:   "client-register-" + string(rune(i)),
			}

The frontend uses SolidJS for reactive state management, as shown in frontend-modern/src/SimpleApp.tsx:3-17:

export default function SimpleApp() {
  const [status, setStatus] = createSignal('Initializing...');
  const [data, setData] = createSignal<any>(null);
  const [wsStatus, setWsStatus] = createSignal('Not connected');

  onMount(() => {
    setStatus('Testing API connection...');

    // Test API
    fetch('/api/health')
      .then((res) => {
        setStatus(`API Status: ${res.status}`);
        return res.json();
      })
      .then((d) => {

Tag-based filtering uses a hash-based color system for consistent visual representation. The implementation in frontend-modern/src/utils/tagColors.ts:8-22 provides deterministic color assignment:

function hashString(str: string): number {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = (hash << 5) - hash + char;
    hash = hash & hash; // Convert to 32bit integer
  }
  return Math.abs(hash);
}

/**
 * Generate a color for a tag based on its text
 * Uses HSL to ensure good visibility and consistent saturation/lightness
 */
export function getTagColor(tag: string): { bg: string; text: string; border: string } {

The search functionality supports complex queries with logical operators, implemented in frontend-modern/src/utils/searchQuery.ts:50-64:

export function parseFilter(term: string): ParsedFilter {
  term = term.trim();

  // Try to parse metric condition (e.g., "cpu>80", "size>1000000000")
  const metricMatch = term.match(/^(\w+)\s*(>|<|>=|<=|=|==)\s*(\d+(?:\.\d+)?)$/i);
  if (metricMatch) {
    const [, field, operator, value] = metricMatch;
    const parsedValue = parseFloat(value);
    if (isNaN(parsedValue)) {
      return {
        type: 'raw',
        rawText: term,
      };
    }

Performance Characteristics

Bundle Impact:

  • Frontend TypeScript: ~37,018 lines compiled
  • Backend Go binary: Minimal runtime footprint
  • WebSocket connections: Concurrent client support tested up to 200 simultaneous connections

Other Considerations:

  • Runtime dependencies: 11 Go modules including WebSocket, OAuth2, and crypto libraries
  • Test coverage: 15 test files covering concurrency and core functionality
  • Build tooling: Go build system with embedded frontend assets

Best for: Small to medium Proxmox deployments requiring real-time monitoring with minimal resource overhead.

Deployment and Scaling Considerations

The installer script supports multiple deployment patterns, from single-node Docker containers to Proxmox LXC containers. The Docker configuration in the README shows resource-efficient deployment:

services:
  pulse:
    image: rcourtman/pulse:latest
    container_name: pulse
    ports:
      - "7655:7655"
    volumes:
      - pulse_data:/data
    environment:
      # Network discovery (usually not needed - auto-scans common networks)
      # - DISCOVERY_SUBNET=192.168.50.0/24  # Only for non-standard networks

Scaling characteristics focus on polling efficiency rather than horizontal scaling. The connection timeout and polling intervals are configurable through environment variables, allowing optimization for larger infrastructures.

Security Architecture

The security model implements multiple layers of protection:

Credential Storage: AES-256-GCM encryption for stored credentials with separate configuration files (.env for auth, system.json for settings, nodes.enc for encrypted node credentials)

Authentication: Multiple methods including bcrypt password hashing (cost 12), API tokens with SHA3-256 hashing, and proxy authentication support for SSO integration

Network Security:

  • Rate limiting (500 req/min general, 10 attempts/min for auth)
  • CSRF protection for state-changing operations
  • Account lockout after failed login attempts
  • Security headers (CSP, X-Frame-Options)

Audit Logging: Comprehensive logging with configurable levels and credential masking in logs

Transport: HTTPS/TLS support with configurable certificate paths

When to Use Pulse

The evidence suggests this project fits well for:

  • Proxmox-centric environments where unified VE and PBS monitoring is required, as demonstrated by the dual-protocol support in the setup scripts
  • Real-time monitoring needs where WebSocket-based updates provide immediate visibility into infrastructure changes
  • Security-conscious deployments requiring credential encryption and comprehensive audit trails, evidenced by the multi-layered security implementation

Consider alternatives when:

  • Large-scale enterprise monitoring is required, as the architecture focuses on efficiency over horizontal scaling
  • Multi-vendor infrastructure needs monitoring beyond Proxmox, since the codebase is specifically tailored to Proxmox APIs
  • Advanced alerting workflows are needed, as the webhook system supports basic notifications but lacks complex routing logic