Scanner Heartbeat
The scanner heartbeat protocol maintains liveness and submits system metrics from each scanner to mipo. Scanners send a POST /scanner/heartbeat every 60 seconds; if a scanner misses two consecutive heartbeats (2-minute timeout), it is marked offline and a scanner-down alarm fires. Results from the legacy scan-id protocol are submitted via POST /scanner/results. Operators debugging connectivity issues should check both the heartbeat timestamp and any authentication errors recorded on the scanner record.
Fields & Columns
| Name | Description |
|---|---|
| version | Optional scanner binary version string, stored for inventory and troubleshooting. |
| hostname | Optional hostname of the machine running the scanner, stored for identification. |
| internalIp | Optional self-reported LAN IP from the scanner NIC. Distinct from the external (connection) IP captured by mipo from the request. |
| capabilities | Optional array of feature flags the scanner supports (e.g., "ipv6", "udp"). Maximum 50 entries. |
| metrics | Optional system metrics: loadAvg1m/5m/15m, memoryTotalBytes, memoryAvailableBytes, networkRxBytes, networkTxBytes, numCpus. Used for health monitoring and scanner-load-high / scanner-memory-high alarms. |
How To
Diagnose a scanner offline alarm
- Check the scanner record in Config > Scanners for the last heartbeat timestamp and any recorded authentication error.
- Verify the scanner process is running on the target host.
- Confirm network connectivity from the scanner host to the ingest endpoint on port 443.
- Check the scanner logs for 401 (invalid API key) or 403 (disabled / IP binding violation) errors.
- If the scanner was re-provisioned, confirm it is using the new API key — old keys are invalidated on re-provisioning.
Understand IP binding enforcement
- IP binding is always enforced on heartbeats (Tier 2 ACL).
- A scanner connecting from an unexpected IP receives 403 with code IP_BINDING_VIOLATION.
- The mismatch counter on the scanner record increments with each violation.
- Release binding via the scanner row actions in Config > Scanners to allow the scanner to re-bind from its new IP.
Gotchas
- IP binding is always enforced on heartbeats — unlike job fetches, there is no exemption for scanners with active jobs. This prevents a stolen API key from bypassing binding via X-Forwarded-For spoofing.
- A successful heartbeat clears the last authentication error on the scanner record. If the scanner recovers from a binding violation, the error is removed automatically.
- The heartbeat auto-recovers scanner_down alarms: when a scanner that was marked offline sends a heartbeat, a scanner_up event is emitted and the alarm auto-resolves.
- Metrics are stored in the TimescaleDB scanner_stats hypertable. If metrics storage fails, the heartbeat still succeeds — metrics are supplementary.
- The legacy POST /scanner/results endpoint co-exists with the job-based path. New scanner implementations should use the job protocol (POST /scanner/jobs/:jobId/complete).
API Calls (2)
| Method | Path | Description |
|---|---|---|
| POST | /scanner/heartbeat | Periodic liveness ping with optional metrics. Body: { version?, hostname?, internalIp?, capabilities?, metrics? }. Uses X-API-Key header. Returns { ok: true, serverTime: string }. |
| POST | /scanner/results | Legacy result upload keyed by scan ID (not job ID). Body: { scanId, results: [...], complete? }. Uses X-API-Key header. Returns { ok: true }. |
Related Pages
- Scanner Jobs — Heartbeat and job dispatch are the two core scanner-to-ingest communication channels
- Scanner Health — Real-time heartbeat status and offline detection for registered scanners
- Scanners — Scanner configuration including IP binding mode and rate limits
- Scanner Binary — Build and deploy the scanner binary before it can send heartbeats