Documentation > API Reference > WebSocket API

WebSocket API

Real-time bidirectional communication for live updates, command execution, and status monitoring.

Overview

SysManage uses WebSockets for real-time communication between the server, web interface, and agents. This enables live status updates, real-time command execution feedback, and instant notifications of system events.

WebSocket Features

  • Real-time Updates - Live host status, package installation progress, and system metrics
  • Bidirectional Communication - Send commands and receive responses in real-time
  • Event Streaming - Subscribe to specific events like host status changes
  • Authentication - JWT-based authentication for secure connections
  • Automatic Reconnection - Built-in reconnection logic for network interruptions

Connection

WebSocket Endpoint

wss://your-server.example.com/ws

Authentication

WebSocket connections require authentication via JWT token passed as a query parameter:

wss://your-server.example.com/ws?token=YOUR_JWT_TOKEN

JavaScript Example

const token = 'YOUR_JWT_TOKEN';
const ws = new WebSocket(`wss://your-server.example.com/ws?token=${token}`);

ws.onopen = function(event) {
    console.log('WebSocket connected');

    // Subscribe to host status updates
    ws.send(JSON.stringify({
        type: 'subscribe',
        channel: 'host_status'
    }));
};

ws.onmessage = function(event) {
    const message = JSON.parse(event.data);
    console.log('Received message:', message);
};

ws.onclose = function(event) {
    console.log('WebSocket disconnected:', event.code, event.reason);
};

ws.onerror = function(error) {
    console.error('WebSocket error:', error);
};

Message Format

All WebSocket messages use JSON format with a standardized structure:

{
  "type": "message_type",
  "channel": "channel_name",
  "data": {
    "key": "value"
  },
  "timestamp": "2024-01-01T12:00:00Z",
  "id": "optional_message_id"
}

Message Types

  • subscribe - Subscribe to a channel
  • unsubscribe - Unsubscribe from a channel
  • command - Execute a command
  • status - Status update message
  • event - System event notification
  • response - Response to a command or request
  • error - Error message

Channels

host_status

Receive real-time updates about host status changes.

Subscribe

{
  "type": "subscribe",
  "channel": "host_status"
}

Example Messages

{
  "type": "event",
  "channel": "host_status",
  "data": {
    "host_id": "uuid",
    "hostname": "web-01",
    "status": "online",
    "previous_status": "offline",
    "timestamp": "2024-01-01T12:00:00Z"
  }
}

package_operations

Monitor package installation, update, and removal operations.

Subscribe

{
  "type": "subscribe",
  "channel": "package_operations",
  "filters": {
    "host_id": "uuid"
  }
}

Example Messages

{
  "type": "event",
  "channel": "package_operations",
  "data": {
    "execution_id": "uuid",
    "host_id": "uuid",
    "hostname": "web-01",
    "operation": "install",
    "package": "nginx",
    "status": "in_progress",
    "progress": 45,
    "message": "Downloading package nginx (1.18.0)"
  }
}

command_execution

Real-time command execution feedback and results.

Subscribe

{
  "type": "subscribe",
  "channel": "command_execution"
}

Execute Command

{
  "type": "command",
  "channel": "command_execution",
  "data": {
    "host_id": "uuid",
    "command": "systemctl status nginx",
    "timeout": 30
  },
  "id": "request_123"
}

Command Response

{
  "type": "response",
  "channel": "command_execution",
  "data": {
    "execution_id": "uuid",
    "host_id": "uuid",
    "command": "systemctl status nginx",
    "status": "completed",
    "exit_code": 0,
    "stdout": "● nginx.service - A high performance web server...",
    "stderr": "",
    "execution_time": 0.156
  },
  "id": "request_123"
}

system_alerts

Receive system alerts and notifications.

Subscribe

{
  "type": "subscribe",
  "channel": "system_alerts",
  "filters": {
    "severity": ["warning", "critical"]
  }
}

Example Messages

{
  "type": "event",
  "channel": "system_alerts",
  "data": {
    "alert_id": "uuid",
    "severity": "warning",
    "title": "High disk usage",
    "message": "Disk usage on /var is 85%",
    "host_id": "uuid",
    "hostname": "web-01",
    "category": "disk_space"
  }
}

user_activity

Monitor user login/logout and activity events.

Subscribe (Admin only)

{
  "type": "subscribe",
  "channel": "user_activity"
}

Example Messages

{
  "type": "event",
  "channel": "user_activity",
  "data": {
    "user_id": "uuid",
    "username": "admin",
    "action": "login",
    "ip_address": "192.168.1.100",
    "user_agent": "Mozilla/5.0...",
    "timestamp": "2024-01-01T12:00:00Z"
  }
}

Live System Monitoring

Real-time Host Metrics

// Subscribe to live metrics for a specific host
{
  "type": "subscribe",
  "channel": "host_metrics",
  "filters": {
    "host_id": "uuid",
    "metrics": ["cpu", "memory", "disk"]
  }
}

// Receive periodic metric updates
{
  "type": "event",
  "channel": "host_metrics",
  "data": {
    "host_id": "uuid",
    "timestamp": "2024-01-01T12:00:00Z",
    "metrics": {
      "cpu_usage": 23.5,
      "memory_usage": 67.2,
      "disk_usage": {
        "/": 45.8,
        "/var": 78.2
      },
      "load_average": [1.2, 1.5, 1.8]
    }
  }
}

Fleet-wide Status

// Subscribe to fleet status updates
{
  "type": "subscribe",
  "channel": "fleet_status"
}

// Receive fleet statistics
{
  "type": "event",
  "channel": "fleet_status",
  "data": {
    "total_hosts": 150,
    "online_hosts": 148,
    "offline_hosts": 2,
    "hosts_with_alerts": 5,
    "pending_operations": 3,
    "last_updated": "2024-01-01T12:00:00Z"
  }
}

Error Handling

Authentication Error

{
  "type": "error",
  "channel": "system",
  "data": {
    "code": "AUTH_FAILED",
    "message": "Invalid or expired JWT token",
    "action": "reconnect_with_valid_token"
  }
}

Channel Subscription Error

{
  "type": "error",
  "channel": "subscription",
  "data": {
    "code": "SUBSCRIPTION_FAILED",
    "message": "Insufficient permissions for channel 'user_activity'",
    "requested_channel": "user_activity"
  }
}

Command Execution Error

{
  "type": "error",
  "channel": "command_execution",
  "data": {
    "code": "COMMAND_FAILED",
    "message": "Host not reachable",
    "host_id": "uuid",
    "execution_id": "uuid"
  },
  "id": "request_123"
}

Best Practices

Connection Management

  • Implement automatic reconnection with exponential backoff
  • Handle connection state changes gracefully
  • Store JWT tokens securely and refresh before expiration
  • Monitor connection health with periodic ping/pong messages

Message Handling

  • Always validate incoming message format
  • Use message IDs for request/response correlation
  • Implement message queuing for offline scenarios
  • Handle out-of-order message delivery

Performance

  • Subscribe only to channels you need
  • Use filters to reduce message volume
  • Unsubscribe from channels when no longer needed
  • Implement client-side message throttling if necessary

Security

  • Never expose JWT tokens in client-side logs
  • Validate all incoming data on the client side
  • Use WSS (WebSocket Secure) in production
  • Implement proper CORS policies

Client Implementation Examples

React Hook Example

import { useState, useEffect, useRef } from 'react';

export const useWebSocket = (url, token) => {
  const [connectionStatus, setConnectionStatus] = useState('Disconnected');
  const [lastMessage, setLastMessage] = useState(null);
  const ws = useRef(null);

  useEffect(() => {
    const connectWebSocket = () => {
      ws.current = new WebSocket(`${url}?token=${token}`);

      ws.current.onopen = () => {
        setConnectionStatus('Connected');
      };

      ws.current.onmessage = (event) => {
        const message = JSON.parse(event.data);
        setLastMessage(message);
      };

      ws.current.onclose = () => {
        setConnectionStatus('Disconnected');
        // Reconnect after 3 seconds
        setTimeout(connectWebSocket, 3000);
      };

      ws.current.onerror = (error) => {
        console.error('WebSocket error:', error);
        setConnectionStatus('Error');
      };
    };

    connectWebSocket();

    return () => {
      if (ws.current) {
        ws.current.close();
      }
    };
  }, [url, token]);

  const sendMessage = (message) => {
    if (ws.current && ws.current.readyState === WebSocket.OPEN) {
      ws.current.send(JSON.stringify(message));
    }
  };

  return { connectionStatus, lastMessage, sendMessage };
};