Skip to content

Notification + Monitoring Stack

Notification gateway, network monitoring, and traffic analysis pipeline.

Architecture

graph TD
    SVC[Services] -->|alerts| APP
    APP["Apprise :8008"] --> TG["Telegram (Homelab group)"]
    MK["MikroTik RB5009"] --> MKTOOLS["mikrotik-tools :8087
9 scheduled jobs"] MK -->|IPFIX :12055| NF2NG["netflow2ng"] MK -->|Exporter metrics| MKTOOLS MK -->|REST API :443/rest| MKTOOLS MKTOOLS --> EXP["Exporter → VictoriaMetrics :8428"] MKTOOLS --> VMALERT["vmalert → Apprise on alert"] MKTOOLS --> NTFYBR["ntfy-bridge → Apprise enriched alerts"] NF2NG --> NTOPNG["ntopng :3004
(DPI + flows, bytes pending fix)"]

Components

Notification

Component Server Port Purpose
Apprise development 8008 Notification gateway → Telegram only
ntfy development 9282 Push notification backend (phone app)

Apprise Config Keys

Key ntfy topic Used by
/notify/all media Generic services
/notify/infra komodo Infrastructure events (ASN update, port-forward, DHCP)
/notify/ros-alerts ros-alerts vmalert → ntfy-bridge enriched alerts

Telegram only — ntfy removed from all apprise config keys.

Sending Notifications

# Stateful (preferred)
curl -X POST http://100.126.172.96:8008/notify/all \
  -H "Content-Type: application/json" \
  -d '{"title": "Alert", "body": "message"}'

# Stateless (backward compatible)
curl -X POST http://100.126.172.96:8008/notify \
  -H "Content-Type: application/json" \
  -d '{"urls": "ntfy://...", "title": "...", "body": "..."}'

Network Monitoring

Component Server Port Purpose
mikrotik-tools development 8087 9 scheduled jobs (supervisord)
Exporter development ros_* metrics → VictoriaMetrics
Web Monitor development 8099 MikroTik dashboard
ntfy-bridge unraid 9093 vmalert webhook → Apprise (enriched)
vmalert unraid 8880 Alert rules → ntfy-bridge
VictoriaMetrics unraid 8428 Metrics storage

Traffic Analysis

Component Server Port Purpose
ntopng development 3004 Web UI + DPI (nDPI 468 protocols)
netflow2ng development 12055 NetFlow v9 collector v0.2.2 → ZMQ → ntopng
GoFlow2 development 12056 NetFlow → Kafka 'network-flows' (raw flow data)
AdGuard unraid 3003 DNS filtering + query log (24h retention)

Two pipelines (parallel):

MikroTik RB5009
  ├─ :12055 → netflow2ng v0.2.2 → ntopng (:3004)     ← UI + DPI
  │    └─ custom_flow_export.lua (embedded in entrypoint)
  │         ↑ scraped by scrape_ntopng.py → DWH
  └─ :12056 → GoFlow2 → Kafka 'network-flows'          ← Raw flow data

Custom Lua endpoint: /lua/custom_flow_export.lua returns JSON with DPI app name, bytes, packets, AS names for all active flows. Works with --disable-login 1 (no auth).

ntopng Community REST API requires Enterprise license — all /lua/rest/v2/ endpoints return 302. Custom Lua endpoint bypasses this limitation.

DWH Data Sources (ntopng scraper)

scrape_ntopng.py runs every 5min:

  1. Queries http://127.0.0.1:3004/lua/custom_flow_export.lua
  2. Enriches flows: nDPI app → service name + category (30+ mappings)
  3. Pushes to DWH /api/v1/logs (provider=ntopng, category=network_flow)
  4. Metadata includes: ndpi_app, service, service_category, bytes, packets, src_as, dst_as

mikrotik-tools Scheduler (10 jobs)

Job Schedule Purpose Alert
ros-backup daily 2:00 Export ROS config → git Git commit
asn-download daily 2:50 iptoasn.com DB (529K ranges) Telegram
vn-ip-update weekly Sun 3:00 APNIC VN IP → MikroTik Telegram
port-forward-sync daily 3:30 Auto VPN exclusion from NAT rules Telegram
firewall-verify daily 4:00 PSD + tarpit rules Log
vpn-check daily 4:30 Double VPN risk check Log
vpn-tunnel-monitor every 30s VPN health + failover Telegram
dhcp-watch every 1min New device alert Telegram
port-monitor every 2min ether1-4 up/down Telegram
ntopng-scrape every 5min ntopng DPI flows → DWH DWH data

Alert Rules (vmalert)

Located in stacks/monitoring/ros-monitoring/alerts.yml:

Alert Severity Condition
WandropSpike critical WAN firewall drops >100/min
QoSCongestion warning WAN queue >0
NetflowDown critical NetFlow collector down
VPNDown warning Gluetun VPN down
WireguardDown warning ROS WireGuard interface down
ConnAnomaly warning Router connections >2000
CriticalDeviceOffline critical IoT/smart device offline
ServerOffline critical Core server offline
ManyDevicesOffline warning 8+ devices offline
BandwidthHog warning Device >500 Mbps
CpuSpikeWithConnectionSpike critical CPU >60% + high connections
CpuSpikeWithTrafficSpike warning CPU >70% + WAN near line rate
CpuP99Anomaly warning CPU P99 >50% for 1h
UnraidDiskThrashing warning Disk spinup >5x/hour (HDD only)
UnraidDiskNeverSpundown info Disk spinning 24h+ (HDD only)
UnraidDiskFlapping warning Disk state change >10x/10min (HDD only)
SpinMonitorDown critical Spin monitor offline

Notification Format

Mobile-optimized for Telegram:

🟡 /dev/sdd spinning 2d5h
ST12000NM0127 | 🌡️45C
📊 I/O:
  • ntfy-bridge ✍️2MB
  • caddy 👁️16KB
Disk never enters standby

VPN Configuration

See docs/mikrotik-vpn-routing-playbook.md for full 6-layer checklist.

WireGuard (ROS)

  • Interface: protonvpn → ProtonVPN VN6
  • Routing: WiFi devices (zone-lan + zone-iot) → VPN, servers + PS5 → WAN
  • Failover: distance 2 WAN backup + health monitor script

VPN Exclusions (auto)

  • port-forwarded address-list: auto-synced from NAT rules
  • zone-servers (.10-.32, .59): excluded by whitelist
  • Tailscale (100.64.0.0/10): excluded in vpn-route table
  • PS5 (.100): auto via port-forwarded list

Health Check

docker exec mikrotik-tools python3 /app/scripts/health_check.py

12-section verification: RouterOS, ports, WireGuard, VPN routing, firewall, DHCP, Apprise, VM, AdGuard, DWH, scripts, state files.

Pitfalls

  • Apprise endpoint is /notify (not /) — POST to / returns 405
  • Bot token from Komodo Variable includes [SECRET] suffix — strip with grep -oP '= \K\S+'
  • cap_drop: ALL requires cap_add: [SETUID, SETGID, CHOWN] for apprise supervisord
  • Bridge fast-forward must be OFF for mangle routing marks to work
  • MSS clamping required for protonvpn (TCP SYN hangs without it)
  • Forward chain must have allow-lan-to-vpn rule before catch-all drop
  • ntopng Community can't receive NetFlow directly — use netflow2ng
  • ntopng flows show 0 bytes via netflow2ng — DPI works but bytes pending fix
  • AdGuard query log retention increased from 6h to 24h