How to create a Zabbix SNMP template from a MIB
Vendors ship MIB files, but Zabbix needs items, discovery rules, value maps and triggers. This guide shows how the pieces map to each other and how to build a template that works on every identical device without hard-coded indexes.
1. What a MIB gives you
A MIB module defines objects under an OID tree. For monitoring, three kinds of definitions matter:
- Scalars: single values such as a firmware version or a global status. They are read with instance
.0, for exampleupsBatteryStatus.0. - Tables: a
...Tableobject (SEQUENCE OF) with an...Entryrow that declares anINDEX. Every column is read ascolumn OID + row index. - Textual conventions: reusable types that carry enumerations (
normal(1), warning(2), critical(3)) and display hints (DISPLAY-HINT "d-1").
Before building anything, load the MIB together with the modules it imports. An unresolved import usually means some OIDs or types are missing, which later shows up as items with the wrong type or no OID at all.
2. Scalars become regular items
Each readable scalar becomes an item of type SNMP agent with the OID of the object plus .0:
- name: 'Battery status'
type: SNMP_AGENT
snmp_oid: '1.3.6.1.2.1.33.1.2.1.0'
key: ups.upsBatteryStatus
valuemap:
name: upsBatteryStatus
Skip objects with MAX-ACCESS not-accessible or accessible-for-notify: they cannot be polled. Objects under a trap branch are also not worth polling.
3. Tables become low-level discovery
Never hard-code table indexes. Two devices of the same model can report the same sensor under different indexes (for example 61 on one unit and 37 on another). Low-level discovery (LLD) asks each device for its own rows.
Zabbix 6.4 and newer: walk[] + SNMP walk to JSON
Create one master item that walks the columns you need to identify rows, and a dependent discovery rule that converts the walk to LLD JSON:
items:
- name: 'Temperature sensors: SNMP walk'
type: SNMP_AGENT
snmp_oid: 'walk[<label column OID>,<port column OID>]'
key: vendor.tempSensorEntry.walk
delay: 1h
history: '0'
value_type: TEXT
discovery_rules:
- name: 'Temperature sensor discovery'
type: DEPENDENT
key: vendor.tempSensorEntry.discovery
master_item:
key: vendor.tempSensorEntry.walk
preprocessing:
- type: SNMP_WALK_TO_JSON
parameters:
- '{#LABEL}'
- '<label column OID>'
- '1'
- '{#PORT}'
- '<port column OID>'
- '1'
Each triple is LLD macro, OID prefix, format. Format 0 keeps the value, 1 converts a Hex-STRING to UTF-8 text, and 2 converts it to a MAC address. {#SNMPINDEX} is always available.
Zabbix 6.0: discovery[]
On 6.0 use a discovery rule of type SNMP agent with discovery[{#LABEL},<label column OID>,{#PORT},<port column OID>].
Item prototypes
Every value column becomes a prototype whose OID ends in .{#SNMPINDEX} and whose name uses a human-readable macro:
item_prototypes:
- name: '{#LABEL}: Temperature'
type: SNMP_AGENT
snmp_oid: '1.3.6.1.4.1.52674.500.4.1.1.1.2.{#SNMPINDEX}'
key: 'vendor.tempSensorValue[{#SNMPINDEX}]'
value_type: FLOAT
units: '°C'
preprocessing:
- type: MULTIPLIER
parameters:
- '0.1'
Tip: use label or position columns (names ending in Label, Name, Descr, Port) as LLD macros. Index or identifier columns rarely belong in items.
4. Value types, units and multipliers
| SNMP type in the MIB | Zabbix type of information | Preprocessing |
|---|---|---|
| INTEGER with enumeration | Numeric (unsigned) | Value map |
| Integer32 that can be negative | Numeric (float) | – |
| Gauge32 / Unsigned32 | Numeric (unsigned) | – |
| Counter32 / Counter64 | Numeric (float) | Change per second |
| Byte counters (octets) | Numeric (float), units bps | Change per second + multiplier 8 |
| TimeTicks | Numeric (float), units uptime | Multiplier 0.01 |
| DisplayString / OCTET STRING | Character or Text | Often Discard unchanged with heartbeat |
Scaling is the most common mistake. Look in three places:
- The UNITS clause:
UNITS "0.1 Hertz"means a raw value of500is 50.0 Hz, so use unitsHzand multiplier0.1."minutes"becomesswith multiplier60. - The DISPLAY-HINT of the textual convention:
"d-1"means one implied decimal (multiplier 0.1),"d-2"two decimals. - The DESCRIPTION: phrases like "in tenths of degrees Celsius", "expressed in hundredths", or "(KB)".
Always use base units (B, bps, s, W). Zabbix adds the k/M/G prefixes itself.
5. Enumerations become value maps
An INTEGER such as normal(1), warning(2), critical(3) becomes a value map with the same name as the textual convention. Items then display critical (3) instead of 3, and triggers stay readable.
6. Triggers with macros and context
For status objects, trigger on explicit error values of the enumeration:
last(/Vendor by SNMP/vendor.tempSensorErrorStatus[{#SNMPINDEX}])=3
For numeric values, put thresholds in user macros so they can be changed without editing the template. Macro context lets one sensor have its own limit:
Problem: last(/Vendor by SNMP/vendor.tempSensorValue[{#SNMPINDEX}])>{$TEMP.MAX.WARN:"{#LABEL}"}
Recovery: last(/Vendor by SNMP/vendor.tempSensorValue[{#SNMPINDEX}])<{$TEMP.MAX.WARN.RECOVERY:"{#LABEL}"}
{$TEMP.MAX.WARN} = 30 (default for all sensors)
{$TEMP.MAX.WARN:"Server room"} = 26 (override on the host)
Thresholds apply to the value after preprocessing, so 30 means 30 °C, not the raw 300.
7. Import and test
- In Zabbix go to Data collection › Templates › Import (6.0: Configuration › Templates › Import).
- Link the template to a host with an SNMP interface and the
{$SNMP_COMMUNITY}macro (or SNMPv3 credentials). - On the discovery rule, use Execute now and check Monitoring › Latest data.
- Compare a few values with
snmpgetto confirm the multipliers.
8. Doing it automatically
MIB Decoder does all of the above in the browser. Load the vendor MIB and optionally an snmpwalk. It picks numeric and status objects, detects units and multipliers, builds value maps, LLD rules with walk[] or discovery[], and trigger prototypes with context macros. Then it exports a template for Zabbix 6.0, 6.4, 7.0 or 7.4. Everything can be edited item by item before export.
Related: How to decode snmpwalk output with a MIB · How to create PRTG lookups from a MIB