tutorial

Monitoring OpenCTI with Vigilmon

OpenCTI is your graph-based cyber threat intelligence platform — but its multi-service architecture (GraphQL API, RabbitMQ, Elasticsearch, MinIO, Redis, connector workers) means more places to fail silently. Here's how to monitor every layer with Vigilmon.

OpenCTI brings STIX2-structured cyber threat intelligence to your analysts — but its distributed architecture means a RabbitMQ backlog, an Elasticsearch cluster going red, or a stopped connector can all silently degrade your intelligence picture without any visible error on the UI. Vigilmon gives you health monitoring for every OpenCTI service: the GraphQL API server, RabbitMQ message broker, Elasticsearch/OpenSearch cluster, connector workers, MinIO object storage, Redis cache, and API response time — so you know the moment any layer fails.

What You'll Set Up

  • HTTP uptime monitor for the OpenCTI API server and React frontend (port 4000)
  • RabbitMQ broker health and queue depth watchdog
  • Elasticsearch/OpenSearch cluster health monitor (port 9200)
  • Connector worker liveness watchdogs per connector
  • MinIO object storage health check (port 9000)
  • Redis connectivity and memory usage monitor (port 6379)
  • GraphQL API response time monitoring

Prerequisites

  • OpenCTI 5.x installed and running (API server accessible on port 4000)
  • OpenCTI API token with read access
  • Access to the OpenCTI host for cron job installation
  • A free Vigilmon account

Step 1: Monitor the OpenCTI API Server

OpenCTI exposes a /health endpoint that confirms the Node.js GraphQL API is running. When this fails, both the React frontend and all connector ingestion stop.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter http://your-opencti-host:4000/health.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Under Response body, set Contains to "status":"alive".
  7. Click Save.

If you serve OpenCTI behind a reverse proxy with TLS termination, use the HTTPS URL and enable Monitor SSL certificate with a 30-day expiry alert.


Step 2: Monitor RabbitMQ Broker Health

RabbitMQ is OpenCTI's message bus — all connector-to-platform communication flows through it. A broker outage means connectors can't deliver ingested intelligence objects to OpenCTI, even though they appear to run correctly. Monitor the management API:

  1. In Vigilmon, click Add MonitorHTTP / HTTPS.
  2. Enter http://your-rabbitmq-host:15672/api/healthchecks/node.
  3. Set Check interval to 1 minute.
  4. Set Expected HTTP status to 200.
  5. Under Authentication, set username guest (or your RabbitMQ admin user) and password.
  6. Under Response body, set Contains to "status":"ok".
  7. Click Save.

Also add a TCP monitor for the AMQP port:

  1. Click Add MonitorTCP Port.
  2. Enter your RabbitMQ host and port 5672.
  3. Set Check interval to 1 minute.
  4. Click Save.

For queue depth monitoring (detect connector backlogs):

#!/bin/bash
# /usr/local/bin/opencti-rabbitmq-queue-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-rabbitmq-queue-heartbeat-id"
RABBITMQ_URL="http://localhost:15672"
RABBITMQ_USER="guest"
RABBITMQ_PASS="guest"

# Check all OpenCTI queues for saturation
MAX_DEPTH=$(curl -s \
  -u "$RABBITMQ_USER:$RABBITMQ_PASS" \
  "$RABBITMQ_URL/api/queues" | \
  python3 -c "
import sys, json
queues = json.load(sys.stdin)
opencti_queues = [q for q in queues if 'opencti' in q.get('name','').lower()]
max_depth = max((q.get('messages', 0) for q in opencti_queues), default=0)
print(max_depth)
" 2>/dev/null || echo "9999")

# Alert if any queue exceeds 1000 messages (connector backlog)
if [ "$MAX_DEPTH" -lt 1000 ]; then
  curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule every 5 minutes with a 10-minute heartbeat interval.


Step 3: Monitor Elasticsearch/OpenSearch Cluster Health

OpenCTI stores all STIX2 intelligence objects in Elasticsearch or OpenSearch. A red cluster health status means data is unreadable and all intelligence queries will fail.

  1. In Vigilmon, click Add MonitorHTTP / HTTPS.
  2. Enter http://your-elasticsearch-host:9200/_cluster/health.
  3. Set Check interval to 2 minutes.
  4. Set Expected HTTP status to 200.
  5. Under Response body, set Does not contain to "status":"red".
  6. Click Save.

For a more precise alert on yellow status (reduced redundancy, not yet failed):

#!/bin/bash
# /usr/local/bin/opencti-es-health-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-es-health-heartbeat-id"
ES_URL="http://localhost:9200"

CLUSTER_STATUS=$(curl -s "$ES_URL/_cluster/health" | \
  python3 -c "import sys,json; print(json.load(sys.stdin).get('status','red'))" 2>/dev/null || echo "red")

if [ "$CLUSTER_STATUS" = "green" ]; then
  curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule every 5 minutes with a 10-minute heartbeat interval. Yellow status should generate a warning (not a page); red should trigger immediate on-call escalation.


Step 4: Monitor Connector Worker Health

OpenCTI's power comes from its 100+ connector ecosystem — but connector processes fail silently. A connector in error state for >24 hours means entire data source categories (MISP events, VirusTotal enrichment, CVE data, TAXII feeds) stop ingesting.

Monitor connector health via the OpenCTI GraphQL API:

#!/bin/bash
# /usr/local/bin/opencti-connector-check.sh
OPENCTI_URL="http://localhost:4000"
OPENCTI_TOKEN="your-opencti-api-token"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-connector-heartbeat-id"

FAILING=$(curl -s \
  -H "Authorization: Bearer $OPENCTI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ connectors { id name active state } }"}' \
  "$OPENCTI_URL/graphql" | \
  python3 -c "
import sys, json, time
data = json.load(sys.stdin)
connectors = data.get('data', {}).get('connectors', [])
failing = [c['name'] for c in connectors
           if c.get('active') and c.get('state') in ('error', None)]
print(len(failing))
" 2>/dev/null || echo "99")

if [ "$FAILING" = "0" ]; then
  curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule every 15 minutes with a 30-minute heartbeat interval. For critical connectors (your primary MISP sync, CVE feed, or threat actor database), create individual heartbeats per connector with tighter intervals.


Step 5: Monitor MinIO Object Storage

MinIO stores file attachments, PDF reports, and exported data in OpenCTI. When MinIO storage fills up or becomes unavailable, analysts can't attach files to threat reports or export intelligence packages.

  1. In Vigilmon, click Add MonitorTCP Port.
  2. Enter your MinIO host and port 9000.
  3. Set Check interval to 1 minute.
  4. Click Save.

For storage utilization:

#!/bin/bash
# /usr/local/bin/opencti-minio-disk-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-minio-disk-heartbeat-id"
MINIO_DATA_DIR="/data/minio"  # adjust to your MinIO data directory

USAGE=$(df "$MINIO_DATA_DIR" | awk 'NR==2 {print $5}' | tr -d '%')

if [ "$USAGE" -lt 80 ]; then
  curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule hourly with a 90-minute heartbeat interval.


Step 6: Monitor Redis Health

Redis serves as OpenCTI's API cache and session store. When Redis becomes unavailable or runs out of memory, API response times degrade and user sessions are dropped.

  1. In Vigilmon, click Add MonitorTCP Port.
  2. Enter your Redis host and port 6379.
  3. Set Check interval to 1 minute.
  4. Click Save.

For memory pressure monitoring:

#!/bin/bash
# /usr/local/bin/opencti-redis-memory-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-redis-memory-heartbeat-id"
REDIS_HOST="localhost"
REDIS_PORT="6379"

USED_MB=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" INFO memory 2>/dev/null | \
  grep "used_memory:" | cut -d: -f2 | tr -d $'\r')
MAX_MB=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" INFO memory 2>/dev/null | \
  grep "maxmemory:" | cut -d: -f2 | tr -d $'\r')

# Only check ratio if maxmemory is configured (non-zero)
if [ -n "$MAX_MB" ] && [ "$MAX_MB" != "0" ]; then
  USAGE_PCT=$(( USED_MB * 100 / MAX_MB ))
  if [ "$USAGE_PCT" -lt 80 ]; then
    curl -s "$HEARTBEAT_URL" > /dev/null
  fi
else
  # No maxmemory limit configured — just check connectivity
  redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" PING > /dev/null 2>&1 && \
    curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule every 5 minutes with a 10-minute heartbeat interval.


Step 7: Monitor GraphQL API Response Time

OpenCTI's knowledge graph queries can be expensive — complex relationship traversals across millions of STIX2 objects cause analyst-facing slowdowns long before they become outages. Track API response time:

  1. Open the HTTP monitor you created in Step 1 (port 4000 health check).
  2. Under Performance, enable Alert on slow response.
  3. Set Alert when response time exceeds 3000 ms.
  4. Click Save.

For the GraphQL endpoint specifically, add a monitored probe:

#!/bin/bash
# /usr/local/bin/opencti-graphql-latency-check.sh
OPENCTI_URL="http://localhost:4000"
OPENCTI_TOKEN="your-opencti-api-token"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/your-graphql-latency-heartbeat-id"

START=$(date +%s%N)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $OPENCTI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ about { version } }"}' \
  "$OPENCTI_URL/graphql")
END=$(date +%s%N)
LATENCY_MS=$(( (END - START) / 1000000 ))

if [ "$HTTP_CODE" = "200" ] && [ "$LATENCY_MS" -lt 3000 ]; then
  curl -s "$HEARTBEAT_URL" > /dev/null
fi

Schedule every 5 minutes with a 10-minute heartbeat interval. The about { version } query is lightweight — if even this is slow, OpenCTI's API layer is under severe pressure.


Step 8: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add your notification channel — email, Slack, PagerDuty, or a webhook to your threat intelligence team's ticketing system.
  2. For Elasticsearch red status and RabbitMQ broker failures, route to PagerDuty — these indicate complete platform failure requiring immediate action.
  3. For connector health and MinIO disk alerts, use Slack or email — these are operational issues that can be addressed within a business day.

Recommended Alert Thresholds

| Monitor | Alert After | Notes | |---|---|---| | API server (port 4000) | 2 failures | Node.js restart causes ~5s gap | | RabbitMQ management API | 2 failures | Brief blip during rolling restart | | RabbitMQ AMQP (port 5672) | 1 failure | AMQP failure = connector blackout | | Elasticsearch cluster | 1 failure | Red status = immediate action | | Connector worker health | 1 failure | >24h staleness already built in | | MinIO TCP (port 9000) | 2 failures | Short restart cycles are normal | | MinIO disk (>80%) | 1 failure | Upload failures are user-visible | | Redis TCP (port 6379) | 2 failures | Fast restart, transient drops | | Redis memory (>80%) | 1 failure | OOM eviction corrupts session state | | GraphQL latency | 1 failure | 3s threshold is well above baseline |


Conclusion

With these monitors in place, Vigilmon gives you full observability across OpenCTI's distributed service architecture: API server availability, RabbitMQ message routing, Elasticsearch data integrity, connector ingestion health, MinIO file storage, Redis cache performance, and GraphQL response time. Your analysts get timely intelligence from a platform you can trust is actually running.

For more self-hosted threat intelligence monitoring guides, visit vigilmon.online.

Monitor your app with Vigilmon

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

Start free →