Configuring snmpd.conf
A working snmpd.conf example is worth more than a thousand words of theory, so this page hands you one and then explains every line of it. The file at /etc/snmp/snmpd.conf is where an SNMP agent learns four things: who's allowed to ask, what group that someone belongs to, which slice of the OID tree that group may see, and whether the whole arrangement is read-only. Those four decisions map to four directives — com2sec, group, view, access. Get them right and you have a tightly scoped, read-only agent that exposes exactly the metrics you monitor and nothing else. Get them wrong and you either expose the whole tree or expose nothing. Let's get them right.
Prerequisites
This page assumes the agent already exists. Before editing the snmpd.conf configuration, confirm:
- snmpd is installed and enabled — if not, start at Install snmpd on Ubuntu/Debian.
- You're running SNMPv2c, which is what the
com2sec/group/accessmodel here targets (v2c is defined across RFC 1901 and RFC 3416). - Root or sudo, since
/etc/snmp/snmpd.confis root-owned. - A shortlist of the OIDs you actually want to publish. You'll add one
viewline each, so know them in advance — the sensor & OID catalog is the reference. - A test machine with
snmpwalkto confirm the rules do what you meant.
Have that OID list ready before you open the file. Writing view lines is faster when you're not tab-switching to look up numbers.

Step-by-step
The classic Net-SNMP access model is four directives stacked in order. Here's how to build them.
- Open the file:
sudo nano /etc/snmp/snmpd.conf - Map a community string to a security name with
com2sec. This says "any request arriving with this community, from this source, is known internally asReadUser":
The# sec.name source community com2sec ReadUser default <password>sourceofdefaultmeans any address; tighten it to a subnet or single IP for real deployments. - Put that security name in a group, bound to the v2c model:
# group sec.model sec.name group ReadGroup v2c ReadUser - Define a view — the set of OIDs the group may read. One
includedline per OID is the safest pattern:# view incl/excl subtree view ReadData included .1.3.6.1.2.1.25.1.1.0 - Tie it together with
access, granting the group read-only rights to that view, with no write and no notify:# group context model level prefix read write notify access ReadGroup "" any noauth exact ReadData none none - Save and restart:
sudo service snmpd restart
Read the four directives as a chain: a community becomes a security name (com2sec), the security name joins a group (group), the group is granted a view (access), and the view enumerates OIDs (view). Break any link and the request is refused. That refusal-by-default is a feature — it's why an allowlisted agent leaks so little.
The access line packs the most fields, so it's worth slowing down on. The context (empty quotes here) and model (any) are rarely changed for a basic v2c setup. noauth is the security level — correct for v2c, which has no authentication layer to require. exact is the view-matching prefix rule. Then come the three permission slots: read points at your view (ReadData), while write and notify are both none. Those two none values are quietly the most important thing in the file. They're what guarantee that even a leaked community can only read — it can never set a value or trigger a notification. A read-only agent is a fundamentally smaller target than a read-write one.
Configuration example
The five directives that make a read-only v2c agent work:
| Directive | Role | Example |
|---|---|---|
agentAddress | listen address/port | udp:161,udp6:[::1]:161 |
com2sec | map community → sec.name | com2sec ReadUser default <password> |
group | bind sec.name to a model | group ReadGroup v2c ReadUser |
view | include an OID subtree | view ReadData included .1.3.6.1.2.1.25.1.1.0 |
access | grant the group read on the view | access ReadGroup "" any noauth exact ReadData none none |
Here's the complete snmpd.conf example, assembled, with the view expanded to a realistic metric set:
# /etc/snmp/snmpd.conf — v2c read-only, allowlisted OIDs
agentAddress udp:161,udp6:[::1]:161 # change 161 to a random port for security
# sec.name source community
com2sec ReadUser default <password>
# group sec.model sec.name
group ReadGroup v2c ReadUser
# view incl/excl subtree
view ReadData included .1.3.6.1.2.1.25.1.1.0
view ReadData included .1.3.6.1.2.1.25.3.3.1.2
view ReadData included .1.3.6.1.2.1.25.2.3.1.6
view ReadData included .1.3.6.1.4.1.2021.10.1.3
# group context model level prefix read write notify
access ReadGroup "" any noauth exact ReadData none none
Each view ... included line publishes exactly one branch. Here that's host uptime (1.3.6.1.2.1.25.1.1.0, hrSystemUptime), per-CPU load (1.3.6.1.2.1.25.3.3.1.2, hrProcessorLoad), storage used (1.3.6.1.2.1.25.2.3.1.6, hrStorageUsed), and 15-minute system load (1.3.6.1.4.1.2021.10.1.3, laLoad from the UCD-SNMP-MIB). The first three live in the Host Resources MIB (RFC 2790). Add or remove lines to match what you chart — the discipline of one line per OID is covered in depth in the OID allowlist guide. Curating that list, rather than exposing .1.3.6.1, is the single biggest thing snmpd.conf configuration does for your security posture.
Verify it works
Restart, then prove the rules behave — both that allowed OIDs answer and that everything else stays hidden.
service snmpd status
From another machine, walk an OID you included, say per-CPU load:
snmpwalk -v2c -c <community> <host>:<port> 1.3.6.1.2.1.25.3.3.1.2
You should get one hrProcessorLoad line per core — the CPU sensor page explains those values. Now confirm the allowlist actually restricts. Walk something you did not include:
snmpwalk -v2c -c <community> <host>:<port> 1.3.6.1.2.1.1
An empty or "no such object" result is the correct answer — it proves the view is fencing the tree the way it should. If everything returns, your access line is probably pointing at a view broader than ReadData, or you left a default rocommunity line uncommented above. Check both.
Security note
The access model is your first line of defence, so treat these as non-negotiable:
- Keep write and notify at
nonein theaccessline — a read-only agent can't be turned into a foothold. - Never expose
.1.3.6.1wholesale. Enumerate OIDs; the shorter the view, the smaller the blast radius. - Replace the community placeholder with a long random value — see Secure the community string.
- Scope the
com2secsource fromdefaultto your poller's subnet or IP. - Comment out stock
rocommunity publiclines that ship in the default file; they quietly override your careful ACL. - Read the wider threat model on the security overview.
The whole point of this file is least privilege. Every extra OID and every wildcard source chips away at it.
Next: connect external monitoring
A precisely configured agent is only half the system. It answers when asked — but something has to keep asking, and ideally from a place that won't fall over at the same moment the server does. Polling from inside the same failure domain is how outages go unnoticed: the box dies, and the poller dies with it. Watching from outside the network closes that gap, which is the reasoning behind double durability — more than one independent source of truth beats a single local one.
ostr.io Monitoring reads the very OIDs you just allowlisted, from outside your infrastructure, and raises real-time email and SMS alerts when a value crosses your threshold. Because it's agentless on the monitoring side, your snmpd.conf is the only server-side config it needs. The add-endpoint guide covers registering the host.
