How To Set Up MRTG
- Install
- Configuration Attempt 1
- Install snmpd
- Configuration Attempt 2
- snmpd Configuration
- Checking with snmpwalk
- Configuration Attempt 3
- snmp-mibs-downloader
- SNMP v3
- MRTG Directory Permissions
- Uptime
- References
Many years ago I used MRTG on OpenBSD to graph network traffic and it worked out of the box. As I remember, there was "getting started" type documentation which could be followed as written and it produced a working result. On Linux today this is not the case, hence this page that describes what needs to be done to have a working MRTG instance.
Install
apt-get install mrtg
The installation process gets indefinitely hung up on "Daemonizing MRTG" step which I figure is part of MRTG initscript.
The same initscript thinks that the presence of a pid file is a sufficient
mechanism to check if a process is running, therefore, after
mrtg is kill -9
'd to get apt
to exit out of its installation,
/etc/init.d/mrtg start
says that MRTG is already running and status
and stop
are similarly useless. stop
doesn't remove the pid file
if it can't kill the process (really) making the system forever think
there is a running mrtg on it until the pid file is manually removed.
rm -f /var/run/mrtg/mrtg.pid
/etc/init.d/mrtg status
for some reason also reports MRTG as "enabled"
or "disabled" rather than "running" or "not running".
Configuration Attempt 1
The reason why mrtg hangs startup during installation is because
there is a skeleton configuration file installed at /etc/mrtg/mrtg.cfg
but it doesn't have any meaningful configuration in it:
# Global configuration
WorkDir: /var/www/html/mrtg
# Put your rules below or run cfgmaker(1)
Now, that probably shouldn't make anything hang, but I am known to have high
expectations.
Running cfgmaker
simply produces its usage output which doesn't
really say how to run it for someone not intimately familiar already with
the tool.
Usage:
cfgmaker [options] [community@]router [[options] [community@]router ...]
We can gather than router
is required, but from there on good luck
figuring out an actual working usage.
We could run:
cfgmaker public@localhost
... which will timeout and produce a rather useless config file because we haven't gotten snmpd installed yet, so let's do that.
Install snmpd
apt-get install snmpd
snmpd seems to be affected by the same initscript braindamage as mrtg:
# /etc/init.d/snmpd status
snmpd is not running ... failed!
# /etc/init.d/snmpd start
Starting SNMP Services: snmpd is already running.
The problem in this case is that I have IPv6 disabled and snmpd is configured to listen on 127.0.0.1 as well as ::1, the latter failing.
In /etc/snmp/snmpd.conf
replace
agentaddress 127.0.0.1,[::1]
with
agentaddress 127.0.0.1
Configuration Attempt 2
If we now run cfgmaker
again, it runs successfully but produces the same
useless empty configuration file as before when it didn't have an snmp
server to talk to:
```
cfgmaker public@localhost
--base: Get Device Info on public@localhost: --base: Vendor Id: Unknown Vendor - 1.3.6.1.4.1.8072.3.2.10 --base: Populating confcache --base: Get Interface Info --base: Walking ifIndex --base: Walking ifType --base: Walking ifAdminStatus --base: Walking ifOperStatus --base: Walking ifMtu --base: Walking ifSpeed
Created by
/usr/bin/cfgmaker public@localhost
Global Config Options
for UNIX
WorkDir: /home/http/mrtg
for NT
WorkDir: c:\mrtgdata
for several Linux, like Debian, RHEL and it's derivatives
WorkDir: /var/www/html/mrtg
for others Linux
WorkDir: /srv/http/mrtg
Global Defaults
to get bits instead of bytes and graphs growing to the right
Options[_]: growright, bits
EnableIPv6: no
System: scan
Description: Linux scan 6.12.11-amd64 #1 SMP PREEMPTDYNAMIC Debian 6.12.11-1 (2025-01-25) x8664
Contact: Me me@example.org
Location: Sitting on the Dock of the Bay
```
The reason why nothing gets returned is because snmpd by default is configured to permit viewing "systemonly" things, whatever that means, and only for SNMP v3 protocol, which I haven't ever seen any guides for how to use.
snmpd Configuration
Back to /etc/snmp/snmpd.conf
, in it I had the following:
```
SECTION: Access Control Setup
This section defines who is allowed to talk to your running
snmp agent.
Views
arguments viewname included [oid]
system + hrSystem groups only
view systemonly included .1.3.6.1.2.1.1 view systemonly included .1.3.6.1.2.1.25.1
rocommunity: a SNMPv1/SNMPv2c read-only access community name
arguments: community [default|hostname|network/bits] [oid | -V view]
Read-only access to everyone to the systemonly view
rocommunity public default -V systemonly rocommunity6 public default -V systemonly
SNMPv3 doesn't use communities, but users with (optionally) an
authentication and encryption string. This user needs to be created
with what they can view with rouser/rwuser lines in this file.
createUser username (MD5|SHA|SHA-512|SHA-384|SHA-256|SHA-224) authpassphrase [DES|AES] [privpassphrase]
e.g.
createuser authPrivUser SHA-512 myauthphrase AES myprivphrase
This should be put into /var/lib/snmp/snmpd.conf
rouser: a SNMPv3 read-only access username
arguments: username [noauth|auth|priv [OID | -V VIEW [CONTEXT]]]
rouser authPrivUser authpriv -V systemonly ```
This section "conveniently" defines the public community but also restricts
it to some useless subset of information. If you want to keep using "public"
community you need to delete the rocommunity
lines, otherwise create
/etc/snmp/snmpd.conf.d/mrtg.conf
with the following contents:
rocommunity notpublic default
Checking with snmpwalk
Install snmpwalk:
apt-get install snmp
To inspect the local snmp instance, run:
snmpwalk -v 2c -c public localhost
If you configured snmpd with the "nonpublic" community as per above:
snmpwalk -v 2c -c nonpublic localhost
The following output means snmpd is running but it does not have any useful MIBs accessible (or, perhaps, loaded? but they are loaded on Debian by default):
% snmpwalk -v 2c -c notpublic localhost
iso.3.6.1.2.1.1.1.0 = STRING: "Linux scan 6.12.11-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.11-1 (2025-01-25) x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (1017) 0:00:10.17
iso.3.6.1.2.1.1.4.0 = STRING: "Me <me@example.org>"
iso.3.6.1.2.1.1.5.0 = STRING: "scan"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
iso.3.6.1.2.1.1.8.0 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.2.1 = OID: iso.3.6.1.6.3.10.3.1.1
iso.3.6.1.2.1.1.9.1.2.2 = OID: iso.3.6.1.6.3.11.3.1.1
iso.3.6.1.2.1.1.9.1.2.3 = OID: iso.3.6.1.6.3.15.2.1.1
iso.3.6.1.2.1.1.9.1.2.4 = OID: iso.3.6.1.6.3.1
iso.3.6.1.2.1.1.9.1.2.5 = OID: iso.3.6.1.6.3.16.2.2.1
iso.3.6.1.2.1.1.9.1.2.6 = OID: iso.3.6.1.2.1.49
iso.3.6.1.2.1.1.9.1.2.7 = OID: iso.3.6.1.2.1.50
iso.3.6.1.2.1.1.9.1.2.8 = OID: iso.3.6.1.2.1.4
iso.3.6.1.2.1.1.9.1.2.9 = OID: iso.3.6.1.6.3.13.3.1.3
iso.3.6.1.2.1.1.9.1.2.10 = OID: iso.3.6.1.2.1.92
iso.3.6.1.2.1.1.9.1.3.1 = STRING: "The SNMP Management Architecture MIB."
iso.3.6.1.2.1.1.9.1.3.2 = STRING: "The MIB for Message Processing and Dispatching."
iso.3.6.1.2.1.1.9.1.3.3 = STRING: "The management information definitions for the SNMP User-based Security Model."
iso.3.6.1.2.1.1.9.1.3.4 = STRING: "The MIB module for SNMPv2 entities"
iso.3.6.1.2.1.1.9.1.3.5 = STRING: "View-based Access Control Model for SNMP."
iso.3.6.1.2.1.1.9.1.3.6 = STRING: "The MIB module for managing TCP implementations"
iso.3.6.1.2.1.1.9.1.3.7 = STRING: "The MIB module for managing UDP implementations"
iso.3.6.1.2.1.1.9.1.3.8 = STRING: "The MIB module for managing IP and ICMP implementations"
iso.3.6.1.2.1.1.9.1.3.9 = STRING: "The MIB modules for managing SNMP Notification, plus filtering."
iso.3.6.1.2.1.1.9.1.3.10 = STRING: "The MIB module for logging SNMP Notifications."
iso.3.6.1.2.1.1.9.1.4.1 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.2 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.3 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.4 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.5 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.6 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.7 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.8 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.9 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.1.9.1.4.10 = Timeticks: (0) 0:00:00.00
iso.3.6.1.2.1.25.1.1.0 = Timeticks: (1018906) 2:49:49.06
iso.3.6.1.2.1.25.1.2.0 = Hex-STRING: 07 E9 02 08 15 28 1D 00 2D 05 00
iso.3.6.1.2.1.25.1.3.0 = INTEGER: 393216
iso.3.6.1.2.1.25.1.4.0 = STRING: "BOOT_IMAGE=/vmlinuz-6.12.11-amd64 root=UUID=17459333-e86f-4607-9de9-7c0b47eeb37e ro net.ifnames=0 biosdevname=0 quiet
"
iso.3.6.1.2.1.25.1.5.0 = Gauge32: 2
iso.3.6.1.2.1.25.1.6.0 = Gauge32: 142
iso.3.6.1.2.1.25.1.7.0 = INTEGER: 0
iso.3.6.1.2.1.25.1.7.0 = No more variables left in this MIB View (It is past the end of the MIB tree)
You would get something like this if you didn't change the rocommunity
line in snmpd configuration. If you changed it as per above, you would
get many pages of output.
Configuration Attempt 3
Now cfgmaker, when trained at the "nonpublic" community, should produce a sensible configuration file:
```
scan# cfgmaker notpublic@localhost
--base: Get Device Info on notpublic@localhost:
--base: Vendor Id: Unknown Vendor - 1.3.6.1.4.1.8072.3.2.10
--base: Populating confcache
--base: Get Interface Info
--base: Walking ifIndex
--snpd: notpublic@localhost: -> 1 -> ifIndex = 1
--snpd: notpublic@localhost: -> 2 -> ifIndex = 2
--snpd: notpublic@localhost: -> 3 -> ifIndex = 3
--base: Walking ifType
--snpd: notpublic@localhost: -> 1 -> ifType = 24
--snpd: notpublic@localhost: -> 2 -> ifType = 6
--snpd: notpublic@localhost: -> 3 -> ifType = 6
--base: Walking ifAdminStatus
--snpd: notpublic@localhost: -> 1 -> ifAdminStatus = 1
--snpd: notpublic@localhost: -> 2 -> ifAdminStatus = 1
--snpd: notpublic@localhost: -> 3 -> ifAdminStatus = 1
--base: Walking ifOperStatus
--snpd: notpublic@localhost: -> 1 -> ifOperStatus = 1
--snpd: notpublic@localhost: -> 2 -> ifOperStatus = 1
--snpd: notpublic@localhost: -> 3 -> ifOperStatus = 2
--base: Walking ifMtu
--snpd: notpublic@localhost: -> 1 -> ifMtu = 65536
--snpd: notpublic@localhost: -> 2 -> ifMtu = 1500
--snpd: notpublic@localhost: -> 3 -> ifMtu = 1500
--base: Walking ifSpeed
--snpd: notpublic@localhost: -> 1 -> ifSpeed = 10000000
--snpd: notpublic@localhost: -> 2 -> ifSpeed = 1000000000
--snpd: notpublic@localhost: -> 3 -> ifSpeed = 0
Created by
/usr/bin/cfgmaker notpublic@localhost
Global Config Options
for UNIX
WorkDir: /home/http/mrtg
for NT
WorkDir: c:\mrtgdata
for several Linux, like Debian, RHEL and it's derivatives
WorkDir: /var/www/html/mrtg
for others Linux
WorkDir: /srv/http/mrtg
Global Defaults
to get bits instead of bytes and graphs growing to the right
Options[_]: growright, bits
EnableIPv6: no
################################################################
System: scan
Description: Linux scan 6.12.11-amd64 #1 SMP PREEMPTDYNAMIC Debian 6.12.11-1 (2025-01-25) x8664
Contact: Me me@example.org
Location: Sitting on the Dock of the Bay
################################################################
Interface 2 >> Descr: 'eth0' | Name: 'eth0' | Ip: '10.2.2.174' | Eth: 'b8-ae-ed-3c-aa-42'
Target[localhosteth0]: #eth0:notpublic@localhost:
SetEnv[localhosteth0]: MRTGINTIP="10.2.2.174" MRTGINTDESCR="eth0"
MaxBytes[localhosteth0]: 125000000
Title[localhosteth0]: Traffic Analysis for eth0 -- scan
PageTop[localhost_eth0]:
Traffic Analysis for eth0 -- scan
System: | scan in Sitting on the Dock of the Bay |
Maintainer: | Me <me@example.org> |
Description: | eth0 |
ifType: | ethernetCsmacd (6) |
ifName: | eth0 |
Max Speed: | 125.0 MBytes/s |
Ip: | 10.2.2.174 (dyn22-24.here) |
```
I omitted the first and third interfaces which were commented out in the
generated configuration - the first one was lo
and the third one was
docker0
, neither one useful for our purposes.
There is also the following incantation that causes the use of v2 SNMP protocol:
cfgmaker --snmp-options=:::::2 notpublic@localhost >/etc/mrtg/mrtg.cfg
I don't know the difference in practice between the protocols, maybe v2 deals with larger counters better (in a 64-bit way, to be precise?).
The difference in the generated output is in the target line:
Target[localhost_eth0]: #eth0:notpublic@localhost:::::2
Save the generated file to where MRTG wants to find it:
cfgmaker --snmp-options=:::::2 notpublic@localhost >/etc/mrtg/mrtg.cfg
... and edit it by hand to remove useless information from the header and maybe change various other details.
Restart MRTG and it should work:
/etc/init.d/mrtg restart
The rendered graphs and index HTML are dumped to /var/www/html/mrtg. Use your favorite web server to look at them.
snmp-mibs-downloader
This is a package that downloads MIBs. Because they are proprietary, apparently.
I thought this package was required for functionality, but apparently not,
it is just needed to map OIDs (numeric) to MIBs (textual) in tools like
snmpwalk
, but MRTG works with OIDs anyway (I guess?) and doesn't care for
the presence of snmp-mibs-downloader.
More info: https://wiki.debian.org/SNMP
SNMP v3
The default protocol version for snmpwalk
appears to be 3.
For snmpd
(as per its configuration file), I don't know.
I haven't seen any resources describing v3 configuration, perhaps
this is v3 - I don't have
the lines referenced in this page at all in my configuration.
MRTG Directory Permissions
MRTG (either the program itself or the Debian init script, though I could
not find any incriminating evidence in the init script)
likes to change the permissions and ownership (!) of the directories given
in MRTG configuration, at least as WorkDir
and Logdir
(note cute
difference in case). MRTG removes world-readable permissions from both
and changes the owning group (to www-data
on my system for the first one
and root
for the second one).
The ownership change is... inappropriate. If it's MRTG doing this and not some Debian-supplied script they need to stop interfering with what is not theirs.
The mode change is obnoxious and, most of all, completely pointless since
MRTG insists on ignoring my Logdir
and putting its log file into the
output directory that is served to the world by the web server!
It "hides" its files from the local users but serves them happily to all
remote clients. Brilliant.
Uptime
MRTG shows "uptime" since either it or snmpd started, not actual system uptime. I don't know who is at fault here for either misrepresenting snmpd runtime as system uptime or misreporting uptime but for a monitoring tool that shows this information by default on every page getting it wrong is shameful.
References
- https://weberblog.net/mrtgrouters2-adding-a-linux-host/
- https://sbarjatiya.com/noteswiki/index.php/UsingMRTGformonitoringhostCPU,memory,disk_etc.
- http://www.debianadmin.com/mrtg-installation-and-configuration-in-debian-based-distributions-2.html
- http://web.archive.org/web/20111206153917/http://theshed.hezmatt.org/rubysnmpd/index.html
- https://github.com/mpalmer/ruby-snmp-agent