Bounding Unicorns

How To Set Up MRTG

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[localhost
eth0]: MRTGINTIP="10.2.2.174" MRTGINTDESCR="eth0" MaxBytes[localhosteth0]: 125000000
Title[localhost
eth0]: 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