For a while i have been trying to see if there was a way to create a Grafana Dashboard for my home router, years ago i invested in a DSL-AC68U and to this day it is still a nifty bit of kit.

One thing that always irritated me though was that this modem/router was never supported by AsusWRT-Merlin and I kind of lost interest in doing anything funky with it and just left it set up as a modem/router.

Then one day after setting up some dashboards for my own little home projects I started googling if there was any way to graph out router metrics to Grafana, while I was doing that I realised that some legendary soul had taken it upon himself to create a DSL-AC68U compatible merlin firmware (you can find the repo here — https://github.com/gnuton/asuswrt-merlin.ng and in the readme it tells you where they discuss any bugs etc)

So off i went and installed it. It worked straight out the box, now I have a few more tweaks and features to play with. When that was done I started seeing what integrations there was or what I could do to export metrics from the router.

I tried the SNMP route and it felt like i had regressed 10 years to when I was starting out in Ops and this was still a thing (yeah, I know it is still a thing in some places). I stopped going down that rabbit hole very quickly.

Then I realised that the Asus router runs an ARMv7 and off the top of my head I remembered you could run Prometheus Node Exporter on these things.

  1. First thing is to enable SSH to the router if you have not already.
  2. Then add a USB drive to the back of it and follow this guide (http://www.algissalys.com/how-to/format-and-partition-usb-asuswrt-routers) to format the USB, I remember using this guide for some parts. If you have any issues formatting the USB drive leave a message and I will see what I can help with.
  3. With SSH enabled and the extra storage added, Let’s go ahead and download a working version of Node Exporter. This is the latest at time of writing. — https://github.com/prometheus/node_exporter/releases/tag/v0.18.1

Now I tried downloading the armv7 version but it just kept triggering illegal arguments errors. So I tried armv5 and it worked.

First find out where you have the USB mounted, you can do that with a

df -h

and it should return something like this

That last line is what you want so let’s cd over there and start downloading.

cd /path/to/your/usb
wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-armv5.tar.gz
tar xvfz node_exporter-0.18.1.linux-armv5.tar.gz
cd /path/to/your/usb/node_exporter-0.18.1.linux-armv5

Here you will find one executable node_exporter , you can try running it to see if it works. and output should look like this

[email protected]:/tmp/mnt/sda/node_exporter-0.18.1.linux-armv5# ./node_exporter
INFO[0000] Starting node_exporter (version=0.18.1, branch=HEAD, revision=3db77732e925c08f675d7404a8c46466b2ece83e)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.12.5, [email protected], date=20190604-16:42:08)  source="node_exporter.go:157"
INFO[0000] Enabled collectors:                           source="node_exporter.go:97"
INFO[0000]  - arp                                        source="node_exporter.go:104"
INFO[0000]  - bcache                                     source="node_exporter.go:104"
INFO[0000]  - bonding                                    source="node_exporter.go:104"
INFO[0000]  - conntrack                                  source="node_exporter.go:104"
INFO[0000]  - cpu                                        source="node_exporter.go:104"
INFO[0000]  - cpufreq                                    source="node_exporter.go:104"
INFO[0000]  - diskstats                                  source="node_exporter.go:104"
INFO[0000]  - edac                                       source="node_exporter.go:104"
INFO[0000]  - entropy                                    source="node_exporter.go:104"
INFO[0000]  - filefd                                     source="node_exporter.go:104"
INFO[0000]  - filesystem                                 source="node_exporter.go:104"
INFO[0000]  - hwmon                                      source="node_exporter.go:104"
INFO[0000]  - infiniband                                 source="node_exporter.go:104"
INFO[0000]  - ipvs                                       source="node_exporter.go:104"
INFO[0000]  - loadavg                                    source="node_exporter.go:104"
INFO[0000]  - mdadm                                      source="node_exporter.go:104"
INFO[0000]  - meminfo                                    source="node_exporter.go:104"
INFO[0000]  - netclass                                   source="node_exporter.go:104"
INFO[0000]  - netdev                                     source="node_exporter.go:104"
INFO[0000]  - netstat                                    source="node_exporter.go:104"
INFO[0000]  - nfs                                        source="node_exporter.go:104"
INFO[0000]  - nfsd                                       source="node_exporter.go:104"
INFO[0000]  - pressure                                   source="node_exporter.go:104"
INFO[0000]  - sockstat                                   source="node_exporter.go:104"
INFO[0000]  - stat                                       source="node_exporter.go:104"
INFO[0000]  - textfile                                   source="node_exporter.go:104"
INFO[0000]  - time                                       source="node_exporter.go:104"
INFO[0000]  - timex                                      source="node_exporter.go:104"
INFO[0000]  - uname                                      source="node_exporter.go:104"
INFO[0000]  - vmstat                                     source="node_exporter.go:104"
INFO[0000]  - xfs                                        source="node_exporter.go:104"
INFO[0000]  - zfs                                        source="node_exporter.go:104"
INFO[0000] Listening on :9100                            source="node_exporter.go:170"
FATA[0000] listen tcp :9100: bind: address already in use  source="node_exporter.go:172"

As you can see it is complaining that the typical exporter port 9100 is in use, this is not a problem, you can change it with a flag.

node_exporter  --web.listen-address=":9101"

Try it out and see if it works (it should)

[email protected]:/tmp/mnt/sda/node_exporter-0.18.1.linux-armv5# ./node_exporter  --web.listen-address=":9102"
INFO[0000] Starting node_exporter (version=0.18.1, branch=HEAD, revision=3db77732e925c08f675d7404a8c46466b2ece83e)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.12.5, [email protected], date=20190604-16:42:08)  source="node_exporter.go:157"
INFO[0000] Enabled collectors:                           source="node_exporter.go:97"
INFO[0000]  - arp                                        source="node_exporter.go:104"
INFO[0000]  - bcache                                     source="node_exporter.go:104"
INFO[0000]  - bonding                                    source="node_exporter.go:104"
INFO[0000]  - conntrack                                  source="node_exporter.go:104"
INFO[0000]  - cpu                                        source="node_exporter.go:104"
INFO[0000]  - cpufreq                                    source="node_exporter.go:104"
INFO[0000]  - diskstats                                  source="node_exporter.go:104"
INFO[0000]  - edac                                       source="node_exporter.go:104"
INFO[0000]  - entropy                                    source="node_exporter.go:104"
INFO[0000]  - filefd                                     source="node_exporter.go:104"
INFO[0000]  - filesystem                                 source="node_exporter.go:104"
INFO[0000]  - hwmon                                      source="node_exporter.go:104"
INFO[0000]  - infiniband                                 source="node_exporter.go:104"
INFO[0000]  - ipvs                                       source="node_exporter.go:104"
INFO[0000]  - loadavg                                    source="node_exporter.go:104"
INFO[0000]  - mdadm                                      source="node_exporter.go:104"
INFO[0000]  - meminfo                                    source="node_exporter.go:104"
INFO[0000]  - netclass                                   source="node_exporter.go:104"
INFO[0000]  - netdev                                     source="node_exporter.go:104"
INFO[0000]  - netstat                                    source="node_exporter.go:104"
INFO[0000]  - nfs                                        source="node_exporter.go:104"
INFO[0000]  - nfsd                                       source="node_exporter.go:104"
INFO[0000]  - pressure                                   source="node_exporter.go:104"
INFO[0000]  - sockstat                                   source="node_exporter.go:104"
INFO[0000]  - stat                                       source="node_exporter.go:104"
INFO[0000]  - textfile                                   source="node_exporter.go:104"
INFO[0000]  - time                                       source="node_exporter.go:104"
INFO[0000]  - timex                                      source="node_exporter.go:104"
INFO[0000]  - uname                                      source="node_exporter.go:104"
INFO[0000]  - vmstat                                     source="node_exporter.go:104"
INFO[0000]  - xfs                                        source="node_exporter.go:104"
INFO[0000]  - zfs                                        source="node_exporter.go:104"
INFO[0000] Listening on :9102                            source="node_exporter.go:170"

It is running, now how do we keep this process running or restart it if it dies…well a good old cron.

Here is a little bash script that i created in the same directory as the node exporter.

#!/bin/bash

pidof node_exporter

if [[ $? -ne 0 ]] ; then
        /path/to/your/usb/node_exporter-0.18.1.linux-armv5/node_exporter  --web.listen-address=":9101" >>/path/to/your/usb/node_exporter-0.18.1.linux-armv5/node_exporter.log 2>&1 &
fi
PLEASE SEE BELOW FOR ADDING THE CRON PERMENTLY TO CRONTAB, I WILL LEAVE THIS HERE FOR NOW BUT THERE IS A BETTER WAY.

Now lets get this into the crontab

crontab -e

* * * * * sh /tmp/mnt/sda/node_exporter-0.18.1.linux-armv5/node_asus.sh

And you can kick start it by

sh /tmp/mnt/sda/node_exporter-0.18.1.linux-armv5/node_asus.sh &

That is it, you now have node exporter running on your router and it is now only waiting for prometheus to start scraping the data.

In your prometheus.yml file you will want to add a scrape config like this

scrape_configs:
  - job_name: 'asusrouter'
    scrape_interval: 5s
    static_configs:
      - targets: ['192.168.1.1:9101']

Now restart Prometheus and you should see metrics appearing.

Now we need Grafana to display some of the data in Prometheus to a dashboard, i have a more or less simple one that I have tweaked to my liking, if you want to add more data, you can see what Prometheus is storing and then graph it out.

Just go to Grafana > Dashboards > Import and that is it.

Here is the link to the gitlab repo which has the bash script and the dashboard json for importing.

Simon Garcia / asus_grafana_dashboard
GitLab.comgitlab.com

Update: 28–10–2019

I noticed an issue with cribs not persisting after rebooting the ASUS router. A deeper look shows that traditional crons get cleared out due to memory management. In short the ASUS router lacks enough memory and clears it out as if you were returning to default settings.

But there is a way to correct that and it is called cru.

So everything you have done up until adding the script to crown is correct. From there on now follow these steps.

Running the below will list the existing added crons. You now just need to add a new one as follows.

cru l

Now lets add the new one

cru a node-exporter '* * * * * sh /tmp/mnt/sda/node_exporter-0.18.1.linux-armv5/node_asus.sh'

And that is it, please leave any questions as comments and ill try and get back to you.