Another one of more or less useful “projects” that got my attention was enabling Zabbix (while monitoring everything else) to also keep track of my Internet speed. There are sources on the Internet that tell you how (easy it is) to do it, but I was not that lucky – had issues trying to set it up. 🤷♂️🙂
What I’m using:
– Zabbix 7 (installed on Ubuntu 24.04)
(https://www.zabbix.com/download?os_distribution=ubuntu)
– Speedtest CLI by Ookla
(https://www.speedtest.net/apps/cli)
– some scripts
So, Zabbix is installed and working, no big surprise there.
Next thing we need to install is Speedtest CLI by Ookla – it’s a simple installation… sort of.
Installing it directly on Zabbix server.
(copy/paste from Ookla’s site – https://www.speedtest.net/apps/cli):
|
1 2 3 4 5 6 7 8 9 10 |
## If migrating from prior bintray install instructions please first... # sudo rm /etc/apt/sources.list.d/speedtest.list # sudo apt update # sudo apt remove speedtest ## Other non-official binaries will conflict with Speedtest CLI # Example how to remove using apt-get # sudo apt remove speedtest-cli sudo apt install curl curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | sudo bash sudo apt install speedtest |
This usually works, but didn’t work for me. 🙂
|
1 |
E: The repository 'https://packagecloud.io/ookla/speedtest-cli/ubuntu noble Release' does not have a Release file. |
|
1 2 |
sudo sed -i 's/noble/jammy/g' /etc/apt/sources.list.d/ookla_speedtest-cli.list sudo apt update |
|
1 |
sudo apt install -y speedtest |
If all goes well, we can check the version:
|
1 2 3 |
speedtest --version # Speedtest by Ookla 1.2.0.84 (ea6b6773cf) Linux/x86_64-linux-musl 6.8.0-85-generic x86_64 # The official command line client for testing the speed and performance of your internet connection. |
And we can test it couple of times manually, to see if it’s working:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
sudo speedtest --accept-license --accept-gdpr --format=json-pretty # { # "type": "result", # "timestamp": "2025-10-10T13:41:42Z", # "ping": { # "jitter": 0.165, # "latency": 9.937, # "low": 9.787, # "high": 10.120 # }, # "download": { # "bandwidth": 6384715, # "bytes": 74974592, # "elapsed": 11900, # "latency": { # "iqm": 88.716, # "low": 15.697, # "high": 539.705, # "jitter": 22.146 # } # }, # "upload": { # "bandwidth": 3615276, # "bytes": 14101120, # "elapsed": 3900, # "latency": { # "iqm": 19.483, # "low": 13.968, # "high": 264.839, # "jitter": 7.657 # } # }, # "packetLoss": 0, # "isp": "ISP", # "interface": { # "internalIp": "INTERNAL_IP", # "name": "eth0", # "macAddr": "MAC_ADDRESS", # "isVpn": false, # "externalIp": "EXTERNAL_IP" # }, # "server": { # "id": 52611, # "host": "ookla.akton.hr", # "port": 8080, # "name": "Akton d.o.o.", # "location": "Zagreb", # "country": "Croatia", # "ip": "81.17.228.30" # }, # "result": { # "id": "RESULT_ID", # "url": "https://www.speedtest.net/result/c/RESULT_ID", # "persisted": true # } # } |
Cool! This works! 🙂
Now the tough part – how can I make Zabbix pick it up?!
Let’s just say that the “normal and direct way” didn’t work that well (Speedtest tool was probably hitting timeouts on the Zabbix side, and had issues in delivering results to Zabbix – seen the timeout errors).
– script that runs and stores/caches measurements (speedtest-cache.sh)
– systemd service and timer that run the script in 15-minute intervals (zabbix-speedtest.service, zabbix-speedtest.timer)
– script that reads measurements from the Zabbix side (speedtest-read.sh)
– Zabbix items representing measured values (template-speedtest-cache.xml)
– widget/graph that shows data in Zabbix
And here it is:
/usr/lib/zabbix/externalscripts/speedtest-cache.sh:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#!/bin/bash SPEEDTEST_BIN="/usr/bin/speedtest" CACHE_DIR="/var/lib/zabbix/speedtest" CACHE_FILE="$CACHE_DIR/latest.json" export HOME="/var/lib/zabbix" mkdir -p "$CACHE_DIR" /usr/bin/timeout 90 "$SPEEDTEST_BIN" --accept-license --accept-gdpr -f json > "$CACHE_FILE.tmp" 2>/dev/null if [ -s "$CACHE_FILE.tmp" ]; then mv "$CACHE_FILE.tmp" "$CACHE_FILE" fi |
/etc/systemd/system/zabbix-speedtest.service:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=Zabbix Speedtest Cache Updater After=network-online.target [Service] User=zabbix Group=zabbix ExecStart=/usr/lib/zabbix/externalscripts/speedtest-cache.sh Nice=10 ProtectSystem=full ProtectHome=yes NoNewPrivileges=yes |
/etc/systemd/system/zabbix-speedtest.timer:
|
1 2 3 4 5 6 7 8 9 10 11 |
[Unit] Description=Run Speedtest for Zabbix every 15 minutes [Timer] OnBootSec=2min OnUnitActiveSec=15min AccuracySec=30s Persistent=true [Install] WantedBy=timers.target |
/usr/lib/zabbix/externalscripts/speedtest-read.sh:
|
1 2 3 4 5 6 7 8 9 |
#!/bin/bash CACHE_FILE="/var/lib/zabbix/speedtest/latest.json" if [ -s "$CACHE_FILE" ]; then cat "$CACHE_FILE" else echo '{"error": "no_data"}' fi |
(manually imported) template-speedtest-cache.xml:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
<?xml version="1.0" encoding="UTF-8"?> <zabbix_export> <version>7.0</version> <templates> <template> <uuid>deaa5b087f2547c1bf8e589bbebfc5b4</uuid> <template>Template Speedtest Ookla JSON</template> <name>Template Speedtest Ookla JSON</name> <groups> <group> <name>Templates</name> </group> </groups> <items> <!-- MASTER ITEM: JSON (cached) --> <item> <uuid>24b5d9052df444de9b015376d2c22bda</uuid> <name>Internet Speedtest JSON (cached)</name> <type>EXTERNAL</type> <key>speedtest-read.sh</key> <delay>60</delay> <history>7d</history> <trends>0</trends> <value_type>TEXT</value_type> <description>Raw JSON output from cached Ookla Speedtest results updated by systemd timer.</description> </item> <!-- DEPENDENT ITEM: DOWNLOAD --> <item> <uuid>1c0c5db38bbd4b579a19d59446a3d939</uuid> <name>Speedtest Download Mbps</name> <type>DEPENDENT</type> <key>speedtest.download</key> <master_item> <key>speedtest-read.sh</key> </master_item> <value_type>FLOAT</value_type> <units>Mbps</units> <preprocessing> <step> <type>JSONPATH</type> <parameters> <parameter>$["download"]["bandwidth"]</parameter> </parameters> </step> <step> <type>MULTIPLIER</type> <parameters> <parameter>0.000008</parameter> </parameters> </step> </preprocessing> </item> <!-- DEPENDENT ITEM: UPLOAD --> <item> <uuid>64cfd5a304b74cb19a027a9c72b9eae0</uuid> <name>Speedtest Upload Mbps</name> <type>DEPENDENT</type> <key>speedtest.upload</key> <master_item> <key>speedtest-read.sh</key> </master_item> <value_type>FLOAT</value_type> <units>Mbps</units> <preprocessing> <step> <type>JSONPATH</type> <parameters> <parameter>$["upload"]["bandwidth"]</parameter> </parameters> </step> <step> <type>MULTIPLIER</type> <parameters> <parameter>0.000008</parameter> </parameters> </step> </preprocessing> </item> <!-- DEPENDENT ITEM: PING --> <item> <uuid>8b3145983e2e47a38e6282f4df537456</uuid> <name>Speedtest Ping ms</name> <type>DEPENDENT</type> <key>speedtest.ping</key> <master_item> <key>speedtest-read.sh</key> </master_item> <value_type>FLOAT</value_type> <units>ms</units> <preprocessing> <step> <type>JSONPATH</type> <parameters> <parameter>$["ping"]["latency"]</parameter> </parameters> </step> </preprocessing> </item> </items> </template> </templates> </zabbix_export> |
Added all the scripts, timers and services, fixed all the permissions, checked that I have data, and now my Internet Speed Monitor widget looks like this (it’s not much, but hey! 🙂):

Cheers!
P.S. I’m not a Zabbix expert, and I’m not responsible if this “solution” causes you any troubles!
P.P.S. Don’t just copy everything from the Internet! It’s full of bad people (and code)! 😉