SNMP Notifier Integration Guide
Version 1.6.9 | Updated: August 08, 2026
SNMP Notifier Integration Guide
This document describes how Alertmanager sends SNMP traps to external Network Management Systems (NMS) using snmp-notifier.
1. Architecture
Data Flow
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Prometheus │────▶│ Alertmanager │────▶│ snmp-notifier │────▶│ NMS/Zabbix │
│ (alert rules) │ │ (webhook) │ │ (UDP trap) │ │ (port 162) │
└─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │ │
prometheus_rules.yml POST JSON SNMP v2c/v3 trap Receives &
fires alert to :9464 to destination processes
Components
| Component | Port | Description |
|---|---|---|
Alertmanager |
9093 |
Routes alerts to snmp-notifier via webhook |
snmp-notifier |
9464 |
Converts JSON alerts to SNMP traps |
NMS |
162 |
Receives SNMP traps (Zabbix, Nagios, etc.) |
snmp-catcher |
8089 |
Test receiver with Web UI (optional) |
Docker Services
# snmp-notifier - production trap sender
snmp-notifier:
image: maxwo/snmp-notifier:v2.1.0
ports: 9464 (internal)
profiles: [snmp]
# snmp-catcher - testing trap receiver
snmp-catcher:
image: hub.friendly-tech.com/monitoring/snmp-catcher:1.6.9
ports: 162/udp, 8089 (Web UI)
profiles: [snmp]
Since 1.6.9 this image is pulled, not built here. It used to be
snmp-catcher:local, rebuilt on the customer’s host whenever a file underprometheus-grafana-stack/snmp-catcher/changed — which needed egress to PyPI and the Alpine mirrors exactly where it is least likely to exist. It is now published by CI to the privatemonitoringproject on the hub, so the host needs a one-timedocker login hub.friendly-tech.com -u ast, and an air-gapped host takes it from the offline bundle as before. A change to the catcher reaches an upgraded stack by pulling the new tag, not by rebuilding.
2. Configuration
Environment Variables (.env)
# ============================================
# SNMP Trap Notifications
# ============================================
# Destination NMS address
SNMP_TRAP_ADDRESS=nms.company.com:162
# SNMP Version: V2c or V3
SNMP_VERSION=V2c
# SNMPv2c settings
SNMP_COMMUNITY=public
# SNMPv3 settings (when SNMP_VERSION=V3)
SNMP_AUTH_USERNAME=snmpuser
SNMP_AUTH_PASSWORD=authpassword
SNMP_PRIV_PASSWORD=privpassword
SNMP_AUTH_PROTOCOL=SHA # SHA or MD5
SNMP_PRIV_PROTOCOL=AES # AES or DES
snmp-notifier Command Line Options
| Option | Default | Description |
|---|---|---|
|
|
Webhook listen address |
|
|
NMS trap destination |
|
|
SNMP version (V2c or V3) |
|
|
SNMPv2c community string |
|
|
Trap send timeout |
|
|
Number of retry attempts |
|
|
Default OID when the alert has no |
|
|
Label with the trigger OID |
|
|
Label with the resolved (clear) OID |
|
|
Label used for the severity varbind |
|
- |
Go template for the description varbind |
The varbinds are also routed under our PEN via
--trap.default-objects-base-oid/--trap.user-objects-base-oid/--trap.user-object— see §5 “How the varbind payload is built” for the full command.
3. SNMP Versions
SNMPv2c
Simple community-based authentication. Good for internal networks.
SNMP_VERSION=V2c
SNMP_COMMUNITY=public
Security: Community string sent in plaintext. Use only on trusted networks.
SNMPv3 (Recommended for Production)
Provides authentication and encryption.
SNMP_VERSION=V3
SNMP_AUTH_USERNAME=snmpuser
SNMP_AUTH_PASSWORD=authpassword123
SNMP_PRIV_PASSWORD=privpassword456
SNMP_AUTH_PROTOCOL=SHA
SNMP_PRIV_PROTOCOL=AES
Security Levels:
| Level | Auth | Encryption | Variables |
|---|---|---|---|
noAuthNoPriv |
No |
No |
username only |
authNoPriv |
Yes |
No |
username + auth password |
authPriv |
Yes |
Yes |
username + auth + priv passwords |
Supported Protocols:
| Type | Options |
|---|---|
Authentication |
SHA (recommended), MD5 |
Privacy |
AES (recommended), DES |
4. Custom OIDs
Using Label in Alert Rules
Add oid label to Prometheus alert rules for custom trap OID:
# prometheus_rules.yml
groups:
- name: infrastructure
rules:
- alert: DbUnreachable
expr: up{job="mysql"} == 0
for: 1m
labels:
severity: critical
oid: "1.3.6.1.4.1.65666.2.0.3" # Custom OID
annotations:
summary: "Database {{ $labels.instance }} is unreachable"
description: "MySQL server has been down for more than 1 minute"
- alert: HighCpuUsage
expr: node_cpu_usage > 90
for: 5m
labels:
severity: warning
oid: "1.3.6.1.4.1.65666.2.0.50" # Custom OID
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
Default OID
If no oid label is present, snmp-notifier uses:
1.3.6.1.4.1.65666.2.0.99 (generic alert)
Resolved OID (trigger vs resolved)
Each rule also carries an oid_resolved label. When the alert is firing,
the trap’s snmpTrapOID.0 is the oid (trigger); when it resolves, the trap’s
snmpTrapOID.0 is the oid_resolved. This is wired in the entrypoint via
--trap.oid-label=oid and --trap.resolution-oid-label=oid_resolved.
labels:
severity: critical
oid: "1.3.6.1.4.1.65666.2.0.41" # sent while firing
oid_resolved: "1.3.6.1.4.1.65666.2.0.42" # sent when it clears
oid_resolved values are frequently shared across a warning/critical pair (both
clear to the same OID), so they need not be unique. Edit both fields in the
config-ui Rules editor (the “OID resolved” field) — see the OID Reference
page for the full trigger/resolved map.
5. MIB File
Location
prometheus-grafana-stack/alertmanager/mibs/ ├── FRIENDLY-TECH-ACS-MIB.txt # MIB definition └── OID-MAPPING.md # OID reference
OID Categories
Infrastructure Alarms (.2.0.1 - .2.0.10)
| Trap OID | Name | Alertmanager alertname | Severity |
|---|---|---|---|
.2.0.1 |
ftAcsCommProblem |
AcsCommProblem |
critical |
.2.0.2 |
ftAcsCommRestored |
AcsCommProblem (resolved) |
clear |
.2.0.3 |
ftDbUnreachable |
DbUnreachable |
critical |
.2.0.4 |
ftDbRestored |
DbUnreachable (resolved) |
clear |
.2.0.5 |
ftTimeDrift |
TimeDrift |
warning |
.2.0.6 |
ftTimeSynced |
TimeDrift (resolved) |
clear |
Licensing Alarms (.2.0.11 - .2.0.20)
| Trap OID | Name | Alertmanager alertname | Severity |
|---|---|---|---|
.2.0.11 |
ftLicenseExpiring |
LicenseExpiring |
warning |
.2.0.12 |
ftLicenseExpired |
LicenseExpired |
critical |
.2.0.13 |
ftLicenseRenewed |
LicenseExpired (resolved) |
clear |
Device Limit Alarms (.2.0.21 - .2.0.40)
| Trap OID | Name | Alertmanager alertname | Severity |
|---|---|---|---|
.2.0.21 |
ftDeviceAccessDenied |
DeviceAccessDenied |
critical |
.2.0.22 |
ftDeviceLimitWarning |
DeviceLimitWarning |
warning |
.2.0.23 |
ftDeviceLimitExceeded |
DeviceLimitExceeded |
critical |
.2.0.25 |
ftTR069LimitWarning |
TR069LimitWarning |
warning |
.2.0.26 |
ftTR069LimitExceeded |
TR069LimitExceeded |
critical |
.2.0.27 |
ftLWM2MLimitWarning |
LWM2MLimitWarning |
warning |
.2.0.28 |
ftLWM2MLimitExceeded |
LWM2MLimitExceeded |
critical |
.2.0.29 |
ftMQTTLimitWarning |
MQTTLimitWarning |
warning |
.2.0.30 |
ftMQTTLimitExceeded |
MQTTLimitExceeded |
critical |
.2.0.31 |
ftUSPLimitWarning |
USPLimitWarning |
warning |
.2.0.32 |
ftUSPLimitExceeded |
USPLimitExceeded |
critical |
Infrastructure Resource Alarms (.2.0.41 - .2.0.70)
| Trap OID | Name | Alertmanager alertname | Severity | Threshold |
|---|---|---|---|---|
.2.0.41 |
ftServerDown |
ServiceDown |
critical |
— |
.2.0.43 |
ftAPIDown |
APIDown |
critical |
— |
.2.0.45 |
ftFrontendDown |
FrontendDown |
critical |
— |
.2.0.47 |
ftCPUUsageWarning |
CPUUsageHigh |
warning |
>=80% |
.2.0.48 |
ftCPUUsageCritical |
CPUUsageCritical |
critical |
>=90% |
.2.0.50 |
ftMemoryUsageWarning |
MemoryUsageHigh |
warning |
>=80% |
.2.0.51 |
ftMemoryUsageCritical |
MemoryUsageCritical |
critical |
>=90% |
.2.0.53 |
ftDiskSpaceWarning |
DiskSpaceFilling |
warning |
>=80% |
.2.0.54 |
ftDiskSpaceCritical |
DiskSpaceCritical |
critical |
>=90% |
.2.0.56 |
ftTCPSessionsWarning |
TCPSessionsWarning |
warning |
>=800 |
.2.0.57 |
ftTCPSessionsCritical |
TCPSessionsCritical |
critical |
>=1000 |
.2.0.59 |
ftHTTPSessionsWarning |
HTTPSessionsWarning |
warning |
>=800 |
.2.0.60 |
ftHTTPSessionsCritical |
HTTPSessionsCritical |
critical |
>=1000 |
.2.0.62 |
ftUDPSessionsWarning |
UDPSessionsWarning |
warning |
>=800 |
.2.0.63 |
ftUDPSessionsCritical |
UDPSessionsCritical |
critical |
>=1000 |
.2.0.65 |
ftHazelcastNodeDown |
HazelcastNodeDown |
critical |
— |
.2.0.67 |
ftMySQLDown |
MySQLDown |
critical |
— |
Variable Bindings (trap payload)
Every trap carries the same 7 variable bindings, rooted under our enterprise
subtree ftAcsNotifyObjects = 1.3.6.1.4.1.65666.1.1. The order and types below
are exactly what snmp-notifier puts on the wire (verified with a live receiver) —
they match the OBJECT-TYPE definitions in the MIB one-to-one:
| Full OID | Name | Type | Source | Example value |
|---|---|---|---|---|
.65666.1.1.1 |
ftAlarmOid |
STRING |
trap OID + labels |
|
.65666.1.1.2 |
ftAlarmSeverity |
STRING |
|
|
.65666.1.1.3 |
ftAlarmDescription |
STRING |
description template |
|
.65666.1.1.4 |
ftAlarmInstance |
STRING |
|
|
.65666.1.1.5 |
ftAlarmName |
STRING |
|
|
.65666.1.1.6 |
ftAlarmSummary |
STRING |
|
|
.65666.1.1.7 |
ftAlarmTimestamp |
STRING |
|
|
Severity is a STRING, not an INTEGER. snmp-notifier emits the raw severity label text (
critical/warning/info/clear). Do not configure your NMS to expect an enumerated integer.
Two standard SNMP varbinds always precede these: sysUpTime.0
(1.3.6.1.2.1.1.3.0) and snmpTrapOID.0 (1.3.6.1.6.3.1.1.4.1.0, whose value is
the per-alert trap OID from the oid label — see §4).
How the varbind payload is built
snmp-notifier splits the payload into default objects and user objects,
each rooted at a configurable base OID. Our entrypoint
(alertmanager/snmp-notifier-entrypoint.sh) points both bases at our PEN so
every field resolves against FRIENDLY-TECH-ACS-MIB instead of the tool’s stock
1.3.6.1.4.1.98789 subtree:
--trap.default-objects-base-oid=1.3.6.1.4.1.65666.1.1 # .1 oid, .2 severity, .3 description
--trap.user-objects-base-oid=1.3.6.1.4.1.65666.1.1 # .4 instance, .5 name, .6 summary, .7 timestamp
--alert.severity-label=severity
--trap.description-template=/etc/snmp-notifier/description.tmpl
--trap.user-object=4=/etc/snmp-notifier/objects/instance.tmpl
--trap.user-object=5=/etc/snmp-notifier/objects/name.tmpl
--trap.user-object=6=/etc/snmp-notifier/objects/summary.tmpl
--trap.user-object=7=/etc/snmp-notifier/objects/timestamp.tmpl
-
Default objects (.1--.3) are built in to snmp-notifier:
.1= trap OID(s)
labels,.2= severity (from--alert.severity-label),.3= the rendered--trap.description-template. -
User objects (.4--.7) are our additions. Each is a tiny Go template in
alertmanager/snmp-notifier-objects/(mounted at/etc/snmp-notifier/objects/) that emits one field, e.g.instance.tmpl→{{ (index .Alerts 0).Labels.instance }}. -
To add an 8th field: create
objects/<field>.tmpl, add--trap.user-object=8=…in the entrypoint loop, and defineftAcsNotifyObjects 8in the MIB. Keep MIB index = OID suffix.
6. Templates
Description Template
Location: alertmanager/snmp-notifier-template.tmpl
{{- /* SNMP Notifier Description Template */ -}}
{{ range .Alerts -}}
[{{ .Status }}] {{ .Labels.alertname }}{{ if .Labels.instance }} @ {{ .Labels.instance }}{{ end }}{{ if .Annotations.summary }}: {{ .Annotations.summary }}{{ end }}
{{ end -}}
Output Example:
[firing] DbUnreachable @ mysql-primary: Database connection failed
Available Template Variables
| Variable | Description |
|---|---|
|
Array of alerts |
|
“firing” or “resolved” |
|
Alert name |
|
Alert severity |
|
Instance label |
|
Alert summary |
|
Alert description |
|
Alert start time |
|
Alert end time (if resolved) |
Custom Template Example
{{- /* Custom template with severity and timestamp */ -}}
{{ range .Alerts -}}
ALERT: {{ .Labels.alertname }}
SEVERITY: {{ .Labels.severity | toUpper }}
INSTANCE: {{ .Labels.instance | default "N/A" }}
STATUS: {{ .Status }}
TIME: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if .Annotations.summary -}}
SUMMARY: {{ .Annotations.summary }}
{{ end -}}
{{ if .Annotations.description -}}
DESCRIPTION: {{ .Annotations.description }}
{{ end -}}
---
{{ end -}}
7. Testing
Using SNMP Trap Catcher (Recommended)
Bootstrap offers built-in testing with SNMP Trap Catcher:
# In the bootstrap config menu:
# Configuration › Alerting › SNMP › "Built-in Trap Catcher (testing)"
# Web UI available at:
http://<server>:8089
Features:
-
Real-time trap display
-
SNMPv2c and SNMPv3 support
-
Persistent storage (survives restarts)
-
Clear button to reset
Manual Testing
Testing with snmptrap Command
# Send test trap directly (bypassing Alertmanager).
# snmpTrapOID.0 = per-alert trap OID (.2.0.3 = ftDbUnreachable), then the 7
# varbinds in wire order. NOTE: severity (.2) is a STRING, not an integer.
snmptrap -v 2c -c public localhost:162 '' \
1.3.6.1.4.1.65666.2.0.3 \
1.3.6.1.4.1.65666.1.1.1 s "1.3.6.1.4.1.65666.2.0.3[alertname=DbUnreachable]" \
1.3.6.1.4.1.65666.1.1.2 s "critical" \
1.3.6.1.4.1.65666.1.1.3 s "[firing] DbUnreachable @ db-1: DB unreachable" \
1.3.6.1.4.1.65666.1.1.4 s "db-1:9104" \
1.3.6.1.4.1.65666.1.1.5 s "DbUnreachable" \
1.3.6.1.4.1.65666.1.1.6 s "Database server unreachable" \
1.3.6.1.4.1.65666.1.1.7 s "2026-07-25T14:03:11Z"
8. Troubleshooting
Common Issues
Traps Not Received
-
Check snmp-notifier is running:
docker ps | grep snmp-notifier docker logs snmp-notifier -
Check firewall allows UDP 162:
# On NMS server sudo tcpdump -i any udp port 162 -
Verify destination is correct:
grep SNMP_TRAP_ADDRESS .env # Should show your NMS address
SNMPv3 Authentication Failed
-
Check credentials match NMS configuration:
grep -E "SNMP_AUTH|SNMP_PRIV" .env -
Verify protocol compatibility:
-
snmp-notifier v2.1.0 supports only auth
SHA/MD5and privacyAES/DES(no SHA-256 / AES-256).SNMP_AUTH_PROTOCOLandSNMP_PRIV_PROTOCOLmust match the NMS exactly — a mismatch fails silently (no trap arrives).
-
-
Check snmp-notifier logs for auth errors:
docker logs snmp-notifier 2>&1 | grep -i auth
Useful Commands
# Restart snmp-notifier
docker compose restart snmp-notifier
# View real-time logs
docker logs -f snmp-notifier
# Check Alertmanager config
curl -s http://localhost:9093/api/v2/status | jq '.config'
# List active alerts
curl -s http://localhost:9093/api/v2/alerts | jq '.[].labels.alertname'
# Resolve test alert
curl -X POST http://localhost:9093/api/v2/alerts \
-H "Content-Type: application/json" \
-d '[{
"labels": {"alertname": "TestSNMPAlert", "severity": "warning"},
"endsAt": "2024-01-01T00:00:00Z"
}]'
Related Documentation
-
Alertmanager Configuration — Channel setup
-
Alertmanager API Guide — Sending alerts programmatically
-
OID Mapping Reference — Full OID list
branch 1.6.9 · commit a862b45d92590285f229f80a6b5d2efabcb3b1b0 · page generated August 08, 2026