Prerequisites
- Suricata 6.x or 7.x running on Linux (bare metal, VM, or Docker)
suricatascCLI available for socket interaction- A free account at vigilmon.online
Part 1: Enable the Suricata Unix socket
Suricata exposes a management interface via a Unix socket. This is the primary way to query Suricata's internal state without reading log files.
Enable the socket in suricata.yaml
unix-command:
enabled: yes
filename: /var/run/suricata/suricata-command.socket
Restart Suricata after changing the config:
sudo systemctl restart suricata
Verify the socket is listening
sudo suricatasc -c /var/run/suricata/suricata-command.socket uptime
Expected response:
{"message": 3842, "return": "OK"}
The message field contains the process uptime in seconds.
Part 2: Build a Suricata HTTP health endpoint
Vigilmon polls HTTP(S) endpoints, so we need a thin wrapper around suricatasc.
Create suricata_health.py
# suricata_health.py
import subprocess
import json
import os
from fastapi import FastAPI, Response
app = FastAPI()
SOCKET_PATH = os.environ.get("SURICATA_SOCKET", "/var/run/suricata/suricata-command.socket")
MIN_RULES = int(os.environ.get("SURICATA_MIN_RULES", "1000"))
def run_suricatasc(command: str) -> dict:
result = subprocess.run(
["suricatasc", "-c", SOCKET_PATH, command],
capture_output=True,
text=True,
timeout=10,
)
if result.returncode != 0:
raise RuntimeError(result.stderr.strip())
return json.loads(result.stdout)
@app.get("/health")
def health(response: Response):
checks = {}
try:
uptime_resp = run_suricatasc("uptime")
if uptime_resp.get("return") == "OK":
checks["suricata_process"] = "ok"
checks["uptime_sec"] = uptime_resp.get("message", 0)
else:
checks["suricata_process"] = "error"
except Exception as e:
checks["suricata_process"] = f"error: {e}"
try:
counters_resp = run_suricatasc("dump-counters")
if counters_resp.get("return") == "OK":
stats = counters_resp.get("message", {})
rules_loaded = stats.get("detect", {}).get("rules_loaded") or 0
if isinstance(rules_loaded, (int, float)) and rules_loaded >= MIN_RULES:
checks["rules_loaded"] = int(rules_loaded)
checks["rules_status"] = "ok"
else:
checks["rules_loaded"] = rules_loaded
checks["rules_status"] = f"warning: only {rules_loaded} rules loaded"
else:
checks["rules_status"] = "error"
except Exception as e:
checks["rules_status"] = f"error: {e}"
try:
iface_resp = run_suricatasc("iface-list")
if iface_resp.get("return") == "OK":
checks["capture_interfaces"] = len(iface_resp.get("message", {}).get("ifaces", []))
else:
checks["capture_interfaces"] = "unknown"
except Exception as e:
checks["capture_interfaces"] = f"error: {e}"
process_ok = checks.get("suricata_process") == "ok"
rules_ok = checks.get("rules_status") == "ok"
healthy = process_ok and rules_ok
response.status_code = 200 if healthy else 503
return {"status": "ok" if healthy else "degraded", "checks": checks}
Run the health service
pip install fastapi uvicorn
sudo uvicorn suricata_health:app --host 0.0.0.0 --port 8093
Or add it as a systemd service:
# /etc/systemd/system/suricata-health.service
[Unit]
Description=Suricata health endpoint
After=suricata.service
[Service]
User=root
WorkingDirectory=/opt/suricata-health
ExecStart=/usr/local/bin/uvicorn suricata_health:app --host 0.0.0.0 --port 8093
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl enable suricata-health
sudo systemctl start suricata-health
Verify the endpoint
curl http://localhost:8093/health
Expected response:
{
"status": "ok",
"checks": {
"suricata_process": "ok",
"uptime_sec": 7203,
"rules_loaded": 45892,
"rules_status": "ok",
"capture_interfaces": 2
}
}
Part 3: Set up HTTP monitoring in Vigilmon
Monitor Suricata process health
- Log in to vigilmon.online and click Add Monitor.
- Choose HTTP(S) monitor.
- Enter:
http://your-suricata-host:8093/health - Set interval to 1 minute.
- Add a keyword check: must contain
"status":"ok". - Add your alert channel.
- Click Save.
Monitor the rule update source
Suricata rule updates typically come from sources like Emerging Threats Open or a private feed. Monitor the update endpoint separately:
- Add a new HTTP(S) monitor.
- Enter the rule feed URL, for example your internal rule distribution server:
https://rules.internal.example.com/health - Set interval to 15 minutes.
- Add your alert channel.
Part 4: Monitor rule freshness
Stale rules are nearly as bad as no rules. Track when suricata-update last ran:
#!/bin/bash
# check_rule_freshness.sh — run via cron
RULE_FILE="/var/lib/suricata/rules/suricata.rules"
MAX_AGE_HOURS=26
STATUS_API="${STATUS_API_URL}/api/rule-status"
if [ ! -f "$RULE_FILE" ]; then
curl -s -X POST "$STATUS_API" \
-H "Content-Type: application/json" \
-d '{"status": "error", "detail": "rule file missing"}'
exit 1
fi
MTIME=$(stat -c %Y "$RULE_FILE")
NOW=$(date +%s)
AGE_HOURS=$(( (NOW - MTIME) / 3600 ))
if [ "$AGE_HOURS" -gt "$MAX_AGE_HOURS" ]; then
curl -s -X POST "$STATUS_API" \
-H "Content-Type: application/json" \
-d "{\"status\": \"stale\", \"age_hours\": $AGE_HOURS}"
else
curl -s -X POST "$STATUS_API" \
-H "Content-Type: application/json" \
-d "{\"status\": \"ok\", \"age_hours\": $AGE_HOURS}"
fi
Add to cron to run every hour:
0 * * * * /opt/suricata/check_rule_freshness.sh
Expose the latest status via an HTTP endpoint and point Vigilmon at it.
Part 5: Docker deployment monitoring
If Suricata runs in Docker, the socket needs to be mounted and the health service needs host-network access:
# docker-compose.yml
version: "3.8"
services:
suricata:
image: jasonish/suricata:7-latest
network_mode: host
cap_add:
- NET_ADMIN
- SYS_NICE
volumes:
- /etc/suricata:/etc/suricata:ro
- /var/log/suricata:/var/log/suricata
- suricata-run:/var/run/suricata
command: ["-i", "eth0", "--unix-socket=/var/run/suricata/suricata-command.socket"]
suricata-health:
image: python:3.12-slim
network_mode: host
command: >
sh -c "pip install -q fastapi uvicorn &&
uvicorn suricata_health:app --host 0.0.0.0 --port 8093"
volumes:
- ./suricata_health.py:/app/suricata_health.py
- suricata-run:/var/run/suricata:ro
working_dir: /app
environment:
SURICATA_SOCKET: /var/run/suricata/suricata-command.socket
volumes:
suricata-run:
Part 6: Webhook alerts for IDS/IPS outages
An IDS/IPS outage is a security event, not just an availability event. Configure Vigilmon webhooks to trigger security-specific incident flows:
from fastapi import FastAPI, Request
import logging
app = FastAPI()
logger = logging.getLogger(__name__)
@app.post("/webhook/vigilmon")
async def vigilmon_alert(request: Request):
payload = await request.json()
status = payload.get("status")
monitor_name = payload.get("monitor_name")
checked_at = payload.get("checked_at")
if status == "down":
logger.critical(
"SECURITY ALERT: Suricata IDS/IPS is DOWN — network threat detection offline",
extra={"monitor": monitor_name, "at": checked_at},
)
await create_security_incident(
title=f"Suricata DOWN: {monitor_name}",
severity="critical",
detail="Network intrusion detection is offline. Threats will not be detected.",
)
await notify_soc(monitor_name)
elif status == "up":
logger.info("Suricata monitor recovered", extra={"monitor": monitor_name})
await resolve_security_incident(monitor_name)
return {"received": True}
Vigilmon sends this payload on status transitions:
{
"monitor_id": "mon_suricata01",
"monitor_name": "Suricata IDS Health",
"status": "down",
"url": "http://ids-host.internal:8093/health",
"checked_at": "2026-07-02T14:00:00Z",
"response_code": 503,
"response_time_ms": 10001
}
Part 7: Multi-sensor fleet monitoring
If you run Suricata on multiple network sensors, add one Vigilmon monitor per host:
| Monitor name | URL | Keyword |
|-------------|-----|---------|
| Suricata — DMZ sensor | http://dmz-ids:8093/health | "status":"ok" |
| Suricata — Core network sensor | http://core-ids:8093/health | "status":"ok" |
| Suricata — Cloud egress sensor | http://cloud-ids:8093/health | "status":"ok" |
Group them in Vigilmon under a "Network Security" project so you have one dashboard for the entire IDS fleet.
Summary
Your Suricata deployment now has layered monitoring:
- Process health endpoint — confirms Suricata is running, has rules loaded, and the capture interface is active, polled every 60 seconds by Vigilmon.
- Rule update source monitor — catches failures in the feed delivery pipeline before rules go stale.
- Rule freshness check — alerts when
suricata-updatehas not run within the expected window. - Security-aware webhooks — DOWN events trigger P1 security incidents, not just standard availability alerts.
- Fleet monitoring — one monitor per sensor so you know exactly which network segment lost IDS coverage.
Vigilmon handles check scheduling, multi-region polling, and alert routing. When Suricata goes down, your SOC team knows within 60 seconds — before attackers figure it out.
Monitor your Suricata IDS/IPS fleet free at vigilmon.online
#suricata #ids #networksecurity #infosec #monitoring