Monitor your Internet with a Raspberry Pi

Internet Service Providers are almost universally despised. They've pushed for the FCC to continue defining 25 Mbps as "high use" broadband, and on top of that they overstate the quality of service they provide. A recently-released map of broadband availability in the US paints a pretty dire picture:

USA map showing areas with limited high speed broadband availability

Here in St. Louis—where I guess I should count my lucky stars we have 'high use' broadband available—I have only two options: I can get 'gigabit' cable Internet from Spectrum, or 75 megabit DSL from AT&T.

That's it.

And you're probably thinking, "Gigabit Internet is great, stop complaining!"

But Spectrum's "gigabit" Internet is 930 megabits down—in ideal conditions—but only 40 megabits up. And that's the highest plan that costs about $150 a month!

Some would die for those speeds (see the map above), but much of the world is better off. And are you really getting the speeds you pay for? You probably don't know.

Grafana speedtest Internet monitoring dashboard

Well, I do, thanks to a $35 Raspberry Pi! And you don't even need a Pi, you could run the software I use on any computer. I just like having a dedicated computer to run all my Internet connection tools, so it's easy to backup or replace, and it doesn't get bogged down.


I have a video that goes along with this blog post, and it's embedded below; skip past it if you prefer reading over viewing.

My Internet Pi

This is my "Internet Pi" (hostname

Internet Raspberry Pi in Rackmount case

I have it installed in a rack (here's a video on the Pi rack), but it could just as easily be on my desk, or sitting by my Internet router.

The most important thing for measuring a network connection is that it's wired. WiFi, especially on the Pi, fluctuates quite a bit and is terrible for monitoring anything besides maybe WiFi signal strength.

The Internet Pi runs Pi-hole for DNS privacy and ad-blocking, and Prometheus and Grafana to provide Internet connection monitoring dashboards.

Having a Pi monitoring my Internet continuously makes it easy to see trends over time, or confirm outages. If you just spot check by running a Speedtest every now and then, you don't have much data to go on.

Setting up Internet Pi

I built the free and open source internet-pi project on GitHub. It's simple to set up, and you can choose which parts of the platform you want to use.

I set up my Internet Pi from another computer, but you could also run the Internet Pi playbook on the Pi itself. Following the install instructions, you need to have a Pi set up with Raspberry Pi OS running on your network, and be able to SSH into the Pi.

Here are the steps to get it going:

  1. Make sure you have Ansible installed:
    1. (If pip3 is not installed) sudo apt-get install -y python3-pip
    2. pip3 install ansible
  2. Download the internet-pi repository to your computer: git clone && cd internet-pi
  3. Install the Ansible Galaxy content that's required to make the playbook work: ansible-galaxy install -r requirements.yml
  4. Make copies of the example.inventory.ini and example.config.yml files (dropping the example. from the filenames) and modify them for your own needs
  5. Run the playbook: ansible-playbook main.yml

The playbook installs all the tools you choose in your configuration file, and once that's done, you should be able to access your Pi's IP address in a web browser to see Pi-hole, or visit the IP address with the port :3030 on the end to see the Grafana dashboards.

Pi-hole -

Setting up Pi-hole

If you wanna use Pi-hole as your home network's DNS server, you should configure your router to advertise the Pi's IP address as the primary DNS server for your whole home network. For extra redundancy, you could actually configure two Pis running Pi-hole, but that's a topic for another post!

But the great thing is, that allows you to see all the DNS requests your devices are making, and make sure (for the most part) things like so-called 'smart' TVs don't send tons of information to advertisers.

Pi-hole is a great first line of defense for your Internet privacy, at least at home, and it even has some other neat tools like a simple DNS server, if you want to use them.

Internet monitoring

The Internet monitoring dashboard is automatically configured for you, but it can take up to an hour before you start seeing data.

Grafana speedtest Internet monitoring dashboard

In my case, it's been running for a couple months, so I can see the Internet connection for the past day, week, or even longer!

The monitoring configuration runs one container that connects to Every 30 minutes or so, another container running Prometheus tells the first container to run a speed test.

NOTE: If you run this monitoring on your own network, be aware that these checks will consume a good amount of data, especially if you run them more frequently. If you have data caps and want to use this monitoring solution, make sure to modify the check interval so you don't get an unexpected overage. ISPs, gotta love 'em!

It stores that data on the Pi, and the Grafana dashboard displays it over time. There's another service that does simple checks on websites you can configure for uptime and HTTP request timing stats—those lightweight checks are performed every few seconds, to give a detailed view when there is more latency in your Internet connection.

One thing I found interesting was my Cable internet connection—which is supposed to be one 930 Mbps—is only really about 700 Mbps on average.

Upload speeds are more consistent, so I begrudgingly pay for this high-tier plan... But I'd be a lot happier with 50 or 100 Mbps of asymmetric data, since I'm not downloading terabytes of files every day.

Starlink monitoring

The main reason I set this stuff up was to compare my Gigabit Cable Internet to SpaceX's Starlink Internet.

Cable Spectrum ISP vs Starlink performance graph

I'll get more into Starlink in a future review, but it looks like on average, when it has a stable connection, I get over 150 Mbps down, and 15 Mbps up, with 40 milliseconds of latency.

Those numbers are less than my Cable ISP; but Starlink also costs less—it's $99/month. And Starlink is also beaming the Internet through satellites up in the sky! For someone who doesn't have a fast Cable option (like rural customers), that's a mind-blowing upgrade from dial-up speeds.

But I mentioned earlier, there's also a Starlink-specific dashboard that gives all the details you'd normally find in the Starlink App.

Starlink connection dashboard

I haven't been actively using the Starlink connection today, so it's a little barren, but it gives a ton of detail, and I'd like to thank Daniel Willcocks (DanOpsTech) for making this possible; I'm using his Docker image and dashboard, and he even adjusted it to work on the Raspberry Pi after I asked about it!

Power monitoring

I also monitor Starlink's power consumption using a Shelly Plug US and a custom Shelly Plug Prometheus exporter I wrote:

Shelly Plug power monitoring Starlink router and dishy dashboard Grafana

Starlink's dish and router use a lot of power (more than you might expect)—but I'll discuss more about that in my Starlink review coming soon! I have a blog post with more about how I set up the Shelly Plug power monitoring.


Now I know exactly how much my ISP is fleecing me for Internet. In Spectrum's case, it looks like they're only giving me about 3/4ths of what I pay for.

I wish I could just pay them $110 a month instead of $150, but if I did that, they'd cancel my service!

I'd like to thank Max Andersen for the original inspiration for the original monitoring configuration, the developers behind Pi-hole for making it free and open source, and especially Miguel who maintains the speedtest exporter, for his help getting some bugs fixed!


I installed Anisble after that cloned the github link after that when i tried to install the ansible-galaxy install -r requirements.yml it failed it got an error

downloading role 'collections', owned by
 [WARNING]: - collections was NOT installed successfully: Content has no field named 'owner'
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.

Interesting—what version of Ansible are you running? If you're running an older version the collection install could mess up. Ideally you need to run the latest version of 2.9, or even better, Ansible 3.0 or 4.0 or later.

I am getting the same error. I was having the problem installing ansible-galaxy and followed the step that a pervious user to run sudo apt install -y ansible inside of the Internet-Pi folder. Once that ran fine, I was able to continue but am now getting an error when I run sudo ansible-galaxy install -r requirements.yml it is coming back with

[WARNING] : - collections was NOT installed successfully: Content has no field named 'owner"

You need to install Ansible 2.9 or later; the version installed via apt is probably 2.8 (check with ansible --version). 2.8 and earlier will not work, as they are not able to work correctly with collections. I would recommend installing Ansible with Pip, e.g. pip3 install ansible.

I'm getting the same collections error:

pi@pinet1:~/internet-pi $ ansible --version
ansible [core 2.11.2]
config file = /home/pi/internet-pi/ansible.cfg
configured module search path = ['/home/pi/.ansible/plugins/modules', '/usr/sh
ansible python module location = /home/pi/.local/lib/python3.7/site-packages/a
ansible collection location = /home/pi/.ansible/collections:/usr/share/ansible
executable location = /usr/bin/ansible
python version = 3.7.3 (default, Jan 22 2021, 20:04:44) [GCC 8.3.0]
jinja version = 2.10
libyaml = False

I am also having this problem:
root@raspberrypi:~# pip3 install ansible
gets me:
ansible [core 2.11.2]

I reinstalled ansible as root because after I installed it as user, it couldn't be found in my path. After installing as root its in /usr/local/bin as expect. However I down see how that would affect the version of ansible that pip pulled down. How can I get a newer version of ansible?

My question would be... where do you find a RasPi 4 8GB for $35? :-)

I'm using the base 2GB model for this; no need for all that extra RAM since these containers are pretty lightweight. The Micro Center near me in St. Louis generally has them in stock, which is nice—not everyone is so lucky!

You can see how this would be confusing, since you focus on the 8GB unit in pictures and videos and don't really enumerate the hardware you used in the blog?

Ah, true. I just realized I do all my testing on 2 GB Pis, and also have the starlink Pi set up using the 2 GB model—however I do have the main "" Pi running on an 8 GB Pi 4.

It's been running for over a month and that amount of RAM is completely unneccessary:

pi@geerli:~ $ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.6Gi       428Mi       5.4Gi        88Mi       1.8Gi       7.1Gi
Swap:          99Mi          0B        99Mi

This would run just fine on a Pi with 1 GB of RAM too (like the earlier 4 model Bs, of which I still have one ;).

I have an 8GB, but I'm using it for VMWare. I started testing with my 1GB that I was setting up for a mirror. Still seems to have plenty of memory to work from. I worked through the missing installation pieces from some of the comments/links here in the discussion. Now I'm off to test things. Thx!

Installed into a VirtualBox VM running Debian. Working great! Thanks!
Now, how do we easily configure the monitored sites? I see it's checking connection to your server. I'd like to use it to monitor some servers at work.

Figured out how to change the pinghosts.yaml after installation, just didn't see a way to make those changes in the original playbook...

One more thing... Changing the module from [http_2xx] to [icmp] in 'prometheus.yaml' and running 'docker-compose up -d' again doesn't change the module type. Any ideas on how to ping instead of looking for http responses?

Thanks for this work. I am trying to set ip up on a Pi that already has prometheus installed for another dashboard. How can I use your project with the existing Prometheus install instead of a second one, or does that matter?

The best thing would be to grab any of the export containers from my project you need, along with any of the Grafana dashboards, and inject them into your existing setup. The internet-pi project itself kind of mixes together a few things that way.

would be possible to add support for others smart plug?
i found some info about mine plug but don't have any idea how to use it

I'm kind of lost at the config and inventory files step. I thought I set them up right but I'm getting a fatal error when I try to run main.yml:

What IP address should I be putting into inventory.ini?

fatal: []: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host port 22: Connection timed out", "unreachable": true}

Gotcha! I think we're getting there. I definitely goofed. I commented out [internet_pi] as well as the public IP line.

It ran through almost everything and then errored:

TASK [Ensure internet-monitoring environment is running.] **********************
fatal: []: FAILED! => {"changed": false, "msg": "Error connecting: Error while fetching server API version: ('Connection aborted.', PermissionError(13, 'Permission denied'))"}

I tried switching out, but it balked because ansible_user is undefined. I added it to the line as defined originally and it continued.

Howdy guys
Great work on this Jeff
Warning total n00b question here
How do you run a playbook ?

Error message

pi@raspberrypi:~ $ ansible --version
ansible 2.10.11
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/pi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/pi/.local/lib/python2.7/site-packages/ansible
executable location = /home/pi/.local/bin/ansible
python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
pi@raspberrypi:~ $ ansible-galaxy install -r requirements.yml

Ok so I am getting somewhere now well a step atleast

pi@raspberrypi:~ $ ansible-playbook main.yml
ERROR! the playbook: main.yml could not be found

I was looking for playbook: main.yml with ssh into pi with filezilla can change files and rename them but couldnt find main.yml anywhere

Hi Aaron,

Did you every find a soilution for this as I am also having exactly ythe same issue. The OS shows main.yml but the Ansible script can't find it.

Regards Hawkeye

I installed ansible with: "pip3 install ansible"

Now when I run "ansible-galaxy install -r requirements.yml" I get:

-bash: ansble-galaxy: command not found

I'm sure I'm missing something basic...

Jeff, new guy to your blog (and to Pi's) but I've been having a lot of fun learning new skills tinkering around with these.

I ran into the same issue of the ansible-galaxy command not being found.. Here is the sequence I ran through to prep my Pi for this little project:
Step 1 - Fresh install of Raspberry Pi OS Lite
Step 2 - sudo apt-get update
Step 3 - sudo apt-get upgrade
Step 4 - sudo apt-get python3-pip (required to get "pip3 install ansible" to work)
Step 5 - sudo apt-get git (required for git command to work for your repository)

I then followed your instructions in the blog post, but when I ran Step 3 - i get the same error. And I checked my spelling multiple times (and CTRL-V'd it from your blog post). Same error:

-bash: asnible-galaxy: command not found.

At one point, it was giving me the error that it could not find ansible-galaxy in /usr/bin. And when i check that locaiton there is nothing related to ansible in that directory.


Hmm, it could be that Ansible is being installed somewhere that's not in the pi user's default $PATH. I'm currently away from my house so can't test on a fresh Pi install, but I know Pip can install a few different places depending on how it's configured. Can you see if /usr/local/bin is in the $PATH? I think Pip might install there by default... but I could be wrong. Or if installing with --user it installs elsewhere, in your home directory.

Hi Jeff,

No I typed the line correctrly but needed to reboot the Pi which fixed that problem. Now I am trying to run the playbook and am coming up with a "Can't find main.yml" error like the post above. Any ideas?
(also as an aside it gives a warning about the software being deprecated and a need toi upgrade Python, what version do we need as I did this all as a fresh install.)

Regards Hawkeye

Got it all working (Thanks!) but I cannot log onto Grafana. Tried admin/admin and also pi/ and admin/ (where is what I set up for the pi account on the Pi), Any ideas?

Thanks Jeff for posting this project! I had it set up quickly except couldnt log in to Grafana.

admin/admin worked for me to login to Grafana. The password "monitoring_grafana_admin_password" is in the config.xml file but didnt apply somehow

Thanks Ken for posting this default password.

Jeff, your awesome for even monitoring this thread. I running your ansible script that I already have PiHole installed with the PADD display. I get the following error. This is the second time I've ran it, and it just ran until it got the error. The first steps ran fine. Running the command under sudo probably won't fix this. Is the some directory permission I running into?

TASK [Ensure internet-monitoring environment is running.] ******************************************************************************
fatal: []: FAILED! => {"changed": false, "msg": "Error connecting: Error while fetching server API version: ('Connection aborted.', PermissionError(13, 'Permission denied'))"}

PLAY RECAP *****************************************************************                  : ok=10   changed=0    unreachable=0    failed=1    skipped=5    rescued=0    ignored=0

hei jeff,
thanks for being! you are awesome and a fun to watch. Especially your bloopers :))
I have a question! from where do you buy rasps?
no amazon answer pls

Most of the time my local Micro Center. Sometimes Vilros, Chicago Electronics Distributors,, or elsewhere, always from one of the recommend Pi resellers linked from the Raspberry Pi website, since they sell at list price and shipping is generally not crazy.

oh, the perks of living the american dream
i heard a lot about microcenter, looks like is not micro at all
i live in europe and here a raspberry is 1 expensive 2 not easy to come around


Any chance you could write a quick little guide on how to uninstall all this?

Somehow I have ruined everything on my Pi.

Sure! Basically uninstall Docker, then delete all the directories created by this project: rm -rf internet-monitoring pi-hole shelly-plug-prometheus starlink-exporter in the Pi home directory. Everything is run as a Docker container, so it should be well-insulated from the rest of the system.

Hi Jeff, thanks for putting this together. I am running into issue with my password in config.yml. I get the following error:

fatal: []: FAILED! => {"ansible_facts": {}, "ansible_included_var_files": [], "changed": false, "message": "
We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  found character that cannot start any token

The error appears to be in '/home/m1cr0g33k/internet-pi/config.yml': line 6, column 18, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

pihole_timezone: America/Chicago
pihole_password: <mypassword<
                 ^ here

If I comment the password field, it gets through most of the installation, but errors at the end with error message provided. I am installing on Proxmox VM running Ubuntu 20.x.

Hi Jeff, this has been very helpful. I started out using internet-monitoring project first. Then you directed me to this project which also uses pihole. The terminal says all 14 tasks are running, but when I visit 3030, it seems to still take me to the original internet-monitoring site. I don't see be see a dashboard to configure pihole. Any hints?

Are you in area that gets 5G wireless home internet? St. Louis, 5G Home Internet is here! Find out if it’s available in your area. www

"Verizon Home Internet services are not currently available at this address. Enter your contact information below to be the first to know when it becomes available."

What speedtest application does this project use? I have found that testing using the speedtest-cli from the raspberry pi apt package system does not test well above 600 - 700 Mbps on my RPi4. I have found that getting the CLI application direct from ( to be much more reliable at testing my Gig connection... a consistent 940Mbps down.

Latency: 11.75 ms (54.57 ms jitter)
Download: 940.78 Mbps (data used: 1.3 GB)
Upload: 107.37 Mbps (data used: 84.5 MB)

I'm looking forward to setting this up on a pi when I find myself some time.

Thanks for all the great work you do.

Hi mate, great work. I have got this working and am only using the internet connection part.
its been running for a few hours now and the ping request parts are working but it doesnt seem that any speedtest has occured.
any ideas? thanks.

It could be the Speedtest container is not running correctly—that can be a problem on 32-bit Pi OS sometimes. Check the GitHub issues to search for the problem.

Hi already have a pihole set up on a Linux vm how can I just set up the monitoring part.

Hey, nice project. Congrats. I just have one question that always bugs me when measuring internet speed. Do you take into account if other devices are using the connection?

Not automatically, no; you should also check in your router which (hopefully) has a traffic monitor to see if anything else is also using bandwidth at the same time as your speedtests, as other devices on the network can affect speeds.

I was able to load this on a Pi where I had already loaded pi-hole successfully. Just be sure to mark the pi-hole portion as false in the config.yml file. Plus I was able to run it locally by properly changing the inventory file.

Thank you for a great set of tools.

I have a pi-hole running on an older pi. It would be interesting to add the internet checking to it but don't want to screw up my configs by running this. Any thoughts on how to add this on top of an existing pi-hole config?

Jeff, love your videos. I'm running into a fatal error:

fatal: []: FAILED! => {"changed": false, "msg": "Unable to start service docker: Job for docker.service failed because t he control process exited with error code.\nSee \"systemctl status docker.service\" and \"journalctl -xe\" for details.\n"}

I also had to install Ansible globally as the Pi would not recognize the "ansible-galaxy collection install -r requirements.yml" command.

Any idea?

My Docker Status after reboot is:

docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-06-25 06:26:11 EDT; 23min ago
Main PID: 641 (dockerd)
Tasks: 12
CGroup: /system.slice/docker.service
└─641 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

When attempting to access via IP:3030 I get a site cannot be reached error.

Well shucky darn. I'll just wipe my PI and start over. I'll be driving through St. Louis next Tuesday as I head to family in KS.

Where might one specify which URL's are used in the UpTime and http request duration graphs?

What server does the speed test choose? Can this be edited to choose a custom server or when closer/further away?

Following the instructions to clone the repo and install Ansible. Is there an additional package/command to install ansible-galaxy ?

So i ran into an issue when it tries to ensure the environment is running, and i've been at it for a while but cant seem to find my way through:

TASK [Ensure internet-monitoring environment is running.] 
fatal: []: FAILED! => {"changed": false, "msg": "Configuration error - \n        Can't find a suitable configuration file in this directory or any\n        parent. Are you in the right directory?\n\n        Supported filenames: docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml\n        "}`

Might be worth mentioning that the step before it ran into this issue, which i solved by creating the directory manually:

failed: [] (item={'src': 'grafana-config.monitoring.j2', 'dest': 'grafana/config.monitoring'}) => {"ansible_loop_var": "item", "changed": false, "checksum": "779c852d9fb7f4210dbcb7ebeeeaa9b91f625fbf", "item": {"dest": "grafana/config.monitoring", "src": "grafana-config.monitoring.j2"}, "msg": "Destination directory /home/pi/internet-monitoring/grafana does not exist"}`