tutorial

Monitoring ChirpStack with Vigilmon

ChirpStack is your open-source LoRaWAN Network Server — but a silent gateway bridge failure or dropped MQTT message means IoT devices go dark. Here's how to monitor every layer with Vigilmon.

ChirpStack is an open-source LoRaWAN Network Server stack that connects LoRa gateways to your applications, handling device join procedures, uplink/downlink routing, ADR, and application integration. When you self-host it, a failed gateway bridge UDP listener or a broken PostgreSQL connection means devices silently disappear from your network — with no alert. Vigilmon closes that gap, giving you real-time visibility across every ChirpStack component from the gateway bridge to the geolocation service.

What You'll Set Up

  • HTTP availability monitor for the ChirpStack Network Server API
  • UDP gateway bridge endpoint health check
  • MQTT integration broker connectivity monitoring
  • Application server API response time tracking
  • Device join and uplink processing pipeline heartbeat
  • PostgreSQL database connectivity check
  • Redis cache health monitoring
  • Geolocation server integration status
  • ADR algorithm service availability

Prerequisites

  • ChirpStack v4 (Network Server + Gateway Bridge + Application Server) running
  • Services accessible on ports 8080 (web/API), 1700 (UDP gateway bridge), 8883 (MQTT)
  • A free Vigilmon account

Step 1: Monitor the Network Server API

The ChirpStack API on port 8080 is the control plane for all device and gateway management. If it's down, no new devices can join and no configuration changes apply.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: http://your-server:8080/api (or https://chirpstack.yourdomain.com/api behind a reverse proxy).
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

ChirpStack's gRPC-gateway returns a JSON object at the root — look for:

http://your-server:8080/api/internal/login

A 200 or 405 (Method Not Allowed on GET) confirms the API is alive.


Step 2: Monitor the Gateway Bridge UDP Endpoint

The ChirpStack Gateway Bridge listens on UDP port 1700 for Semtech UDP Packet Forwarder protocol from your LoRa gateways. Vigilmon's TCP monitor can probe the port, but UDP requires a custom check.

Add a TCP check as a basic connectivity signal:

  1. Click Add MonitorTCP Port.
  2. Enter host and port 1700.
  3. Set interval to 2 minutes.

For true UDP gateway bridge health, create a heartbeat that sends a synthetic keepalive packet:

#!/bin/bash
# Send a UDP ping and verify the gateway bridge is responding
echo -n '\x02\x00\x00\x00\xAA\x55\xC0\xFF' | \
  nc -u -w 2 your-server 1700 > /dev/null 2>&1

# ChirpStack Gateway Bridge won't return data for malformed packets,
# but nc exit 0 confirms UDP port is accepting datagrams
if nc -zu your-server 1700 2>/dev/null; then
  curl -s https://vigilmon.online/heartbeat/GATEWAY_BRIDGE_HEARTBEAT_ID
fi

Schedule this every 2 minutes with cron. If the bridge process crashes, the UDP socket disappears and the check fails.


Step 3: Monitor MQTT Integration Broker

ChirpStack publishes device uplinks, join events, and downlink acknowledgements to MQTT. Applications subscribe to these topics to receive device data. A broken MQTT connection means application integrations go silent.

Monitor the MQTT port with TCP:

  1. Click Add MonitorTCP Port.
  2. Enter host and port 8883 (TLS) or 1883 (plaintext).
  3. Set interval to 1 minute.

Add an active MQTT connectivity check:

#!/bin/bash
# Subscribe briefly and check for a retained message or connection success
timeout 5 mosquitto_sub -h your-server -p 8883 \
  --cafile /etc/chirpstack/ca.crt \
  -t "chirpstack/gateways/+/stats" -C 0 2>/dev/null
# Exit 0 = connected successfully, exit 1 = connection refused/timeout
if [ $? -ne 124 ] && [ $? -ne 1 ]; then
  curl -s https://vigilmon.online/heartbeat/MQTT_HEARTBEAT_ID
fi

Step 4: Monitor Application Server API Response Times

The Application Server REST/gRPC API is what your application code calls to list devices, send downlinks, and read uplink history. Slow response times indicate database pressure or a memory leak.

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://your-server:8080/api/devices?limit=1&applicationId=1
  3. Add a header: Grpc-Metadata-Authorization: Bearer YOUR_JWT_TOKEN
  4. Set Check interval to 2 minutes.
  5. Enable Response time alerting and set threshold to 2000ms.

You can generate a long-lived API token in ChirpStack under API KeysGlobal API Keys for use in monitoring scripts.


Step 5: Monitor Device Join and Uplink Pipeline

The most critical path in ChirpStack is the join-accept and uplink flow: gateway receives packet → bridge forwards to NS → NS authenticates → routes to AS → AS publishes to MQTT. A failure at any hop means devices appear online to gateways but messages never reach your application.

Create a synthetic device that sends test uplinks on a schedule:

#!/usr/bin/env python3
import base64
import requests
import sys

API_URL = "http://your-server:8080/api"
HEADERS = {"Grpc-Metadata-Authorization": "Bearer YOUR_API_TOKEN"}
TEST_DEVICE_EUI = "0000000000000001"

# Check the device was last seen within the last 10 minutes
resp = requests.get(
    f"{API_URL}/devices/{TEST_DEVICE_EUI}",
    headers=HEADERS, timeout=10
)

if resp.status_code == 200:
    requests.get("https://vigilmon.online/heartbeat/UPLINK_PIPELINE_HEARTBEAT_ID",
                 timeout=5)
else:
    print(f"Device check failed: {resp.status_code}", file=sys.stderr)
    sys.exit(1)

For production monitoring, use the ChirpStack built-in device stats endpoint to verify uplinks are arriving within your expected interval.


Step 6: Monitor PostgreSQL Connectivity

ChirpStack stores device sessions, gateways, applications, and event logs in PostgreSQL. A lost database connection causes join rejections and uplink failures.

#!/bin/bash
pg_isready -h localhost -p 5432 -U chirpstack -d chirpstack
if [ $? -eq 0 ]; then
  curl -s https://vigilmon.online/heartbeat/POSTGRES_HEARTBEAT_ID
fi

Create a Vigilmon cron heartbeat:

  1. Click Add MonitorCron Heartbeat.
  2. Set expected interval to 5 minutes.
  3. Paste the heartbeat URL into the script above.
  4. Add to cron: */5 * * * * /opt/checks/chirpstack-db.sh

Step 7: Monitor Redis Cache

ChirpStack uses Redis to store device sessions, downlink frames, and ADR history. Redis failure degrades performance significantly and breaks session continuity for devices mid-join.

#!/bin/bash
redis-cli -h localhost -p 6379 ping | grep -q PONG
if [ $? -eq 0 ]; then
  curl -s https://vigilmon.online/heartbeat/REDIS_HEARTBEAT_ID
fi

Also add a TCP port monitor:

  1. Click Add MonitorTCP Port.
  2. Host and port 6379.
  3. Interval: 1 minute.

Step 8: Monitor Geolocation Server Integration

If you run the ChirpStack Geolocation Server (for TDOA location of devices), it exposes its own API. Monitor it with an HTTP check:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://your-server:8005/ (default geolocation server port — adjust to your config).
  3. Set expected status to 200 or 404 (confirms the server is responding).
  4. Interval: 5 minutes.

Step 9: Monitor ADR Algorithm Service

ChirpStack's Adaptive Data Rate service runs as part of the Network Server but can be isolated. Verify it's processing by checking that devices are receiving ADR commands:

#!/bin/bash
# Query last ADR adjustment timestamp for a test device
TOKEN=$(curl -s -X POST http://your-server:8080/api/internal/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"YOUR_PASSWORD"}' \
  | jq -r '.jwt')

STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  -H "Grpc-Metadata-Authorization: Bearer $TOKEN" \
  "http://your-server:8080/api/devices/YOUR_TEST_DEVICE_EUI/linkMetrics?start=$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)&end=$(date -u +%Y-%m-%dT%H:%M:%SZ)&aggregation=HOUR")

if [ "$STATUS" = "200" ]; then
  curl -s https://vigilmon.online/heartbeat/ADR_HEARTBEAT_ID
fi

Step 10: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
  2. For the gateway bridge UDP monitor, set Consecutive failures to 3 — a single missed check can be a transient network blip.
  3. For the database heartbeat, set it to 1 — a PostgreSQL failure is immediately actionable.
  4. Create an alert escalation: Slack for the first failure, PagerDuty after 5 consecutive failures.

Summary

| Monitor | Target | What It Catches | |---|---|---| | HTTP | :8080/api | Network Server API down | | TCP | :1700 | Gateway bridge crash | | TCP | :8883 | MQTT broker unreachable | | TCP | :6379 | Redis down | | Heartbeat | UDP probe | Gateway bridge not accepting packets | | Heartbeat | MQTT connect check | MQTT auth or TLS failure | | Heartbeat | API response time | Application Server slow/overloaded | | Heartbeat | Uplink pipeline check | End-to-end message flow broken | | Heartbeat | pg_isready | PostgreSQL connection lost | | Heartbeat | Device link metrics | ADR service stalled |

ChirpStack powers LoRaWAN networks that span cities — device batteries last years, and an outage can take hours to detect through field reports. With Vigilmon watching every hop in the data path, you know the moment the gateway bridge stops accepting packets or the join server starts rejecting devices.

Monitor your app with Vigilmon

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

Start free →