Skip to main content

Connection

Connect to a container’s WebSocket for real-time monitoring. Endpoint: ws://localhost:8070/ws/:internal_id?token=<token>
const ws = new WebSocket('ws://localhost:8070/ws/my-server-001?token=lightd_token');

ws.onopen = () => {
  console.log('Connected to container');
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Event:', data.event, data);
};

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

ws.onclose = () => {
  console.log('Disconnected from container');
};
Authentication:
  • Token passed as query parameter
  • Token validated on connection
  • Connection closed if token expires during session
  • Single-use tokens are consumed on connection

Outbound Events (Server → Client)

Stats Event

Real-time container statistics with change detection.
{
  "event": "stats",
  "cpu_usage": 25.5,
  "memory_usage": 134217728,
  "memory_limit": 536870912,
  "network_rx": 1024,
  "network_tx": 2048,
  "block_read": 4096,
  "block_write": 8192
}
Fields:
  • cpu_usage - CPU percentage (0-100 per core)
  • memory_usage - Memory used in bytes
  • memory_limit - Memory limit in bytes
  • network_rx - Network bytes received
  • network_tx - Network bytes transmitted
  • block_read - Disk bytes read
  • block_write - Disk bytes written
Stats are only sent when values change (change detection enabled).

Console Output

Real-time console output from the container.
{
  "event": "console",
  "data": "Server started on port 25565\n"
}

Console Duplicate

Duplicate of console output for compatibility.
{
  "event": "console duplicate",
  "data": "Server started on port 25565\n"
}

Container State Events

Installing:
{
  "event": "event",
  "data": "installing"
}
Installed (Ready):
{
  "event": "event",
  "data": "installed"
}
Starting:
{
  "event": "event",
  "data": "starting"
}
Running (Pattern Matched):
{
  "event": "event",
  "data": "running"
}
Stopping:
{
  "event": "event",
  "data": "stopping"
}
Exit (Container Stopped):
{
  "event": "event",
  "data": "exit"
}

Daemon Messages

System messages from Lightd.
{
  "event": "daemon_message",
  "data": "Server started"
}
Common messages:
  • "Container started" - Container started successfully
  • "Server started" - Server detected as running (pattern matched)
  • "Container stopped" - Container stopped
  • "Container restarted" - Container restarted
  • "Error: <message>" - Error occurred

Historical Logs

Historical logs when requested.
{
  "event": "logs",
  "data": "Previous log line 1\nPrevious log line 2\n"
}

Inbound Events (Client → Server)

Send Command

Execute a command in the container.
ws.send(JSON.stringify({
  event: 'send_command',
  command: 'echo "Hello World"\n'
}));
Event:
{
  "event": "send_command",
  "command": "echo 'Hello World'\n"
}
Include \n at the end for command execution.

Power Actions

Start Container:
{
  "event": "power",
  "action": "start"
}
Kill Container:
{
  "event": "power",
  "action": "kill"
}
Restart Container:
{
  "event": "power",
  "action": "restart"
}
// Start
ws.send(JSON.stringify({
  event: 'power',
  action: 'start'
}));

// Kill
ws.send(JSON.stringify({
  event: 'power',
  action: 'kill'
}));

// Restart
ws.send(JSON.stringify({
  event: 'power',
  action: 'restart'
}));

Request Logs

Request historical logs from the container.
ws.send(JSON.stringify({
  event: 'request_logs'
}));
Event:
{
  "event": "request_logs"
}
Response: Server sends logs event with historical data.

Complete Example

// Connect to WebSocket
const ws = new WebSocket('ws://localhost:8070/ws/my-server-001?token=lightd_token');

// Handle connection open
ws.onopen = () => {
  console.log('Connected to container');
  
  // Request historical logs
  ws.send(JSON.stringify({
    event: 'request_logs'
  }));
};

// Handle incoming messages
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  switch(data.event) {
    case 'console':
      console.log('Console:', data.data);
      break;
      
    case 'stats':
      console.log('CPU:', data.cpu_usage + '%');
      console.log('Memory:', data.memory_usage, '/', data.memory_limit);
      break;
      
    case 'event':
      console.log('State:', data.data);
      break;
      
    case 'daemon_message':
      console.log('System:', data.data);
      break;
      
    case 'logs':
      console.log('Historical logs:', data.data);
      break;
  }
};

// Handle errors
ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

// Handle close
ws.onclose = () => {
  console.log('Disconnected from container');
};

// Helper functions
function sendCommand(cmd) {
  ws.send(JSON.stringify({
    event: 'send_command',
    command: cmd + '\n'
  }));
}

function startContainer() {
  ws.send(JSON.stringify({
    event: 'power',
    action: 'start'
  }));
}

function stopContainer() {
  ws.send(JSON.stringify({
    event: 'power',
    action: 'kill'
  }));
}

function restartContainer() {
  ws.send(JSON.stringify({
    event: 'power',
    action: 'restart'
  }));
}

// Usage
sendCommand('echo "Hello from WebSocket"');
startContainer();

Connection Lifecycle

1

Connect

Client connects with token in query parameter
2

Validate

Server validates token
3

Subscribe

Client subscribed to container events
4

Stream

Real-time stats and console output streamed
5

Monitor

Token validity checked periodically
6

Disconnect

Connection closed if token expires or client disconnects

Error Handling

Invalid Token:
  • Connection rejected with 401 status
  • WebSocket closes immediately
Token Expired:
  • Connection closes with close code
  • Client should reconnect with new token
Container Not Found:
  • Connection accepted but no events sent
  • Client should verify container exists

Performance Notes

  • Stats sent only when values change (reduces bandwidth)
  • Console output streamed in real-time
  • Multiple clients can connect to same container
  • Each client gets independent event stream

Best Practices

Implement automatic reconnection with exponential backoff for production applications.
Buffer outgoing messages if connection is temporarily lost to avoid data loss.
Filter events client-side based on your application needs to reduce processing overhead.
Monitor token expiration and refresh before it expires to maintain connection.