tutorial

Uptime monitoring for Soketi WebSocket server

Soketi is the self-hosted Pusher-compatible WebSocket server that teams reach for when they want real-time without the Pusher price tag. It powers presence c...

Soketi is the self-hosted Pusher-compatible WebSocket server that teams reach for when they want real-time without the Pusher price tag. It powers presence channels, private channels, and client events in your application. When Soketi goes down, every Pusher client in your app loses its connection silently — users see stale data and your application appears frozen.

This tutorial covers production-grade uptime monitoring for Soketi using Vigilmon. We will walk through:

  • Monitoring the Soketi HTTP API health endpoint
  • TCP port monitoring for WebSocket availability
  • Monitoring the app list endpoint
  • SSL certificate monitoring and alerts
  • Webhook notifications on DOWN/UP events

Prerequisites

  • Soketi running (Docker, npm, or bare metal)
  • A free account at vigilmon.online

Part 1: Soketi health and API endpoints

Soketi exposes an HTTP API on a dedicated port (default: 6001). This port serves both the WebSocket upgrade path and the HTTP API used by your backend to publish events.

Start Soketi

# Using Docker
docker run -p 6001:6001 \
  -e SOKETI_DEFAULT_APP_ID=app-id \
  -e SOKETI_DEFAULT_APP_KEY=app-key \
  -e SOKETI_DEFAULT_APP_SECRET=app-secret \
  quay.io/soketi/soketi:latest-16-alpine

# Using npm
npx @soketi/soketi start \
  --config=soketi.json

Check the health endpoint

Soketi does not expose a dedicated /health endpoint by default — instead, a GET request to the root of the HTTP API or a channel query confirms the server is running:

# Check if the server is responding
curl http://localhost:6001/

# Check the app-specific info endpoint (requires authentication signature)
curl "http://localhost:6001/apps/app-id/channels" \
  -H "Authorization: Bearer your-auth-signature"

For a simple liveness check without authentication, Soketi returns HTTP 200 for the root path:

curl -I http://localhost:6001/
# HTTP/1.1 200 OK

Soketi config file

{
  "host": "0.0.0.0",
  "port": 6001,
  "appManager": {
    "driver": "array",
    "array": {
      "apps": [
        {
          "id": "app-id",
          "key": "app-key",
          "secret": "app-secret",
          "maxConnections": 200,
          "enableClientMessages": true,
          "enabled": true,
          "maxBackendEventsPerSecond": 100
        }
      ]
    }
  },
  "metrics": {
    "enabled": true,
    "driver": "prometheus",
    "host": "0.0.0.0",
    "port": 9601,
    "prometheus": {
      "prefix": "soketi_"
    }
  }
}

Docker Compose setup

# docker-compose.yml
version: "3.8"

services:
  soketi:
    image: quay.io/soketi/soketi:latest-16-alpine
    environment:
      SOKETI_DEFAULT_APP_ID: "app-id"
      SOKETI_DEFAULT_APP_KEY: "app-key"
      SOKETI_DEFAULT_APP_SECRET: "app-secret"
      SOKETI_DEBUG: "0"
    ports:
      - "6001:6001"
      - "9601:9601"

Part 2: HTTP monitoring in Vigilmon

Monitor Soketi availability

  1. Log in to vigilmon.online and click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. Enter: https://ws.example.com/ (your Soketi endpoint behind a reverse proxy with TLS)
  4. Set interval to 1 minute.
  5. Set expected HTTP status to 200.
  6. Click Save.

Monitor the channels endpoint

The Pusher-compatible channels API confirms Soketi's core functionality — not just that the server process is alive, but that channel management is operational:

# Soketi channels endpoint (requires HMAC signature)
curl "http://localhost:6001/apps/app-id/channels"

Because this endpoint requires authentication, it is best monitored from an internal health check script that signs the request and pings a Vigilmon heartbeat (see Part 4).

Monitor the Soketi metrics endpoint

If Prometheus metrics are enabled (port 9601), you can monitor the metrics endpoint as a health signal:

  1. In Vigilmon, click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. Enter: http://ws.example.com:9601/metrics
  4. Add a keyword check: soketi_
  5. Set interval to 1 minute.
  6. Click Save.

Keep the metrics port firewalled from public access — allow only Vigilmon's IP ranges or serve it on an internal network.


Part 3: TCP port monitoring for WebSocket availability

A Soketi server can respond to HTTP requests on port 6001 while the WebSocket upgrade is failing due to a load balancer misconfiguration, proxy timeout, or TLS termination issue. TCP monitoring catches this independently:

  1. In Vigilmon, click Add Monitor.
  2. Choose TCP monitor.
  3. Enter host: ws.example.com and port: 443 (or 6001 if not behind a proxy).
  4. Set interval to 1 minute.
  5. Click Save.

If your Soketi deployment separates the HTTP API port from the WebSocket port, add a TCP monitor for each:

| Monitor name | Host | Port | Purpose | |---|---|---|---| | Soketi WS port | ws.example.com | 443 | WebSocket connections | | Soketi API port | api.example.com | 6001 | Backend event publishing |


Part 4: Heartbeat monitoring for scheduled publishers

Applications that push events to Soketi on a schedule — dashboard refreshes, notification batches, live score updates — can fail silently. The Soketi server stays healthy while your publisher stops delivering data to channels.

Set up a Vigilmon heartbeat monitor

  1. In Vigilmon, click Add Monitor.
  2. Choose Heartbeat monitor.
  3. Name it: Soketi scheduled publisher.
  4. Set interval to match your publish schedule (e.g., 5 minutes).
  5. Copy the generated heartbeat URL.

Ping the heartbeat from your publisher

// Node.js example using Pusher server SDK
const Pusher = require('pusher');
const axios = require('axios');

const pusher = new Pusher({
  appId: 'app-id',
  key: 'app-key',
  secret: 'app-secret',
  host: 'ws.example.com',
  port: '6001',
  useTLS: false,
});

const VIGILMON_HEARTBEAT_URL = process.env.VIGILMON_HEARTBEAT_URL;

async function publishDashboardUpdate() {
  await pusher.trigger('dashboard', 'data-update', {
    timestamp: Date.now(),
    metrics: await getLatestMetrics(),
  });

  // Signal successful completion to Vigilmon
  await axios.get(VIGILMON_HEARTBEAT_URL);
}

publishDashboardUpdate().catch(err => {
  console.error('Publisher failed:', err);
  // Heartbeat NOT pinged — Vigilmon will alert after interval expires
});
# Python example
import pusher
import httpx

client = pusher.Pusher(
    app_id='app-id',
    key='app-key',
    secret='app-secret',
    host='ws.example.com',
    port=6001,
    ssl=False,
)

VIGILMON_HEARTBEAT_URL = 'https://vigilmon.online/heartbeat/your-heartbeat-id'

def publish_live_scores():
    scores = fetch_latest_scores()
    client.trigger('scores', 'update', {'scores': scores})
    httpx.get(VIGILMON_HEARTBEAT_URL, timeout=5)

Part 5: SSL certificate monitoring

When Soketi is behind Nginx, Caddy, or another reverse proxy that terminates TLS, the certificate must stay valid for WebSocket connections (wss://) to work. A certificate expiry breaks every active WebSocket client instantly.

Nginx reverse proxy for Soketi

server {
    listen 443 ssl;
    server_name ws.example.com;

    ssl_certificate /etc/letsencrypt/live/ws.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ws.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:6001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
    }
}

Add SSL monitoring in Vigilmon

  1. In Vigilmon, click Add Monitor.
  2. Choose SSL monitor.
  3. Enter: ws.example.com
  4. Set alert threshold to 14 days before expiry.
  5. Add your alert channel.

Add SSL monitors for all domains that serve WebSocket traffic, including any separate API subdomains.


Part 6: Webhook alerts

Configure a webhook in Vigilmon to receive DOWN/UP events and trigger your incident pipeline:

  1. In Vigilmon, go to Alert ChannelsAdd Channel.
  2. Choose Webhook.
  3. Enter your webhook URL.
  4. Click Save.
// Webhook receiver
import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhook/vigilmon', (req, res) => {
  const { monitor_name, status, url, response_code, checked_at } = req.body;

  if (status === 'down') {
    console.error('[VIGILMON] Soketi DOWN', {
      monitor: monitor_name,
      url,
      code: response_code,
      at: checked_at,
    });
    notifyOnCall({ monitor: monitor_name, url });
  } else if (status === 'up') {
    console.info('[VIGILMON] Soketi recovered', { monitor: monitor_name, at: checked_at });
  }

  res.sendStatus(204);
});

Vigilmon sends this payload on state transitions:

{
  "monitor_id": "mon_abc123",
  "monitor_name": "Soketi HTTP",
  "status": "down",
  "url": "https://ws.example.com/",
  "checked_at": "2026-06-30T08:01:00Z",
  "response_code": 503,
  "response_time_ms": 1204
}

Summary

Your Soketi deployment now has four layers of monitoring:

  1. HTTP monitor — confirms the Soketi HTTP API is responding on port 6001, polled every 60 seconds.
  2. TCP port monitor — verifies the WebSocket port is reachable independently of the application layer.
  3. Heartbeat monitor — catches silent publisher failures before users notice stale channel data.
  4. SSL monitor — alerts you 14 days before certificate expiry, before WebSocket connections start breaking.

Vigilmon handles check scheduling, multi-region polling, alert routing, and uptime history — your team is notified within 60 seconds of any Soketi failure.


Monitor your Soketi server free at vigilmon.online

#soketi #websocket #pusher #realtime #monitoring #devops

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →