
This morning i found out that Pi-hole has an small API and can be called from the endpoint: admin/api.php? so i decided to create an small plugin for Centreon/Nagios in order to extract (almost) all the information possible that can be graphed
- Number of DNS queries in a day.
- Number and percentage of ads blocked.
- Number of clients using Pi-hole as their DNS server.
- Number of queries classified by IPv4, IPv6, PTR, SRV, etc…
The API is quite limited so i could not do too much. The following are some graphs that I am getting now using the plugin.




The plugin is the following one, but as I always say, you can find it in my GitHub updated.
#!/bin/bash # Nagios plugin to work with Pihole API ########### By @deividgdt ########### plugin_version="1.3" ##################################### function info() { case "$1" in token) echo "[i] The file ${api_token_file} does not exist or it's empty." echo "[i] You can get your token from the value WEBPASSWORD in the file /etc/pihole/setupVars.conf" echo "[i] Just put in the file ${api_token_file} and that's it." echo "" echo "[i] Example:" echo " centreon-engine@centreon # touch ${api_token_file}" echo " centreon-engine@centreon # echo 'PASTE_YOUR_TOKEN_HERE' >> ${api_token_file}" exit 1; ;; usage) echo "[i] Usage $0 -h pihole_ipaddress -s [ clients || queries || ads ] || -i || -q" echo "" echo "[i] -s (summary)" echo " - clients: Number of clients using Pihole as their DNS server" echo " - queries: Number of DNS queries" echo " - ads: Number and percentage of ads blocked." echo "" echo "[i] -i (information)" echo " - show the version of the plugin" echo "[i] -q" echo " - queries by type AAAA, A, SOA, TXT, PTR, ANY, SRV, IPV4, IPV6" ;; version) echo "[v] plugin by @deividgdt https://github.com/deividgdt - version: ${plugin_version}" ;; esac } function apiCall() { local obj=$1 local token=$2 pihole_api_tempfile="/usr/lib/nagios/plugins/pihole_api.tmp" case $obj in "summary") pihole_api_output=$(curl http://${pihole_ipadd}/admin/api.php?${obj} 2> /dev/null | sed 's/","/n/g ; s/"//g' > ${pihole_api_tempfile}) ;; "getQueryTypes") pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed "s,),,g ; s,(,,g ; s/,"/n/g ; s/"//g" > ${pihole_api_tempfile}) ;; esac } function getApiToken() { # Default token file location api_token_file="/usr/lib/nagios/plugins/apihole.token" # If the file does not exist if [ ! -f ${api_token_file} ]; then info token else export api_token=$(cat ${api_token_file}) # If the the api_token var is NULL because the file is empty (?) if [ -z ${api_token} ]; then echo "[e] Token is NULL"; info token fi fi } function functSummary() { apiCall "summary" # The summary option passed case "${summary_opt}" in clients) unique_clients=$(cat ${pihole_api_tempfile} | grep unique_clients | cut -f2 -d":") echo "THERE ARE ${unique_clients} HOSTS UP|Total=${unique_clients}" ;; queries) dns_queries_today=$(cat ${pihole_api_tempfile} | grep dns_queries_today | cut -f2 -d":") echo "DNS QUERIES TODAY ${dns_queries_today}|Total=${dns_queries_today}" ;; ads) ads_percentage_today=$(cat ${pihole_api_tempfile} | grep ads_percentage_today | cut -f2 -d":") ads_blocked_today=$(cat ${pihole_api_tempfile} | grep ads_blocked_today | cut -f2 -d":") echo "ADS BLOCKED TODAY ${ads_blocked_today} , PERCENTAGE = ${ads_percentage_today} %|Total=${ads_blocked_today} Percentage=${ads_percentage_today}%" ;; *) echo "Incorrect arugment > ${summary_opt} < for the option -s"; info "usage" exit 1; ;; esac } function functGetQueryTypes() { # This function requires a token getApiToken # Calling the api apiCall "getQueryTypes" "${api_token}" # Local vars for query types local ipv4=$(cat ${pihole_api_tempfile} | grep -io "ipv4:.*" | cut -f2 -d":") local ipv6=$(cat ${pihole_api_tempfile} | grep -io "ipv6:.*" | cut -f2 -d":") local any=$(cat ${pihole_api_tempfile} | grep -io "any:.*" | cut -f2 -d":") local srv=$(cat ${pihole_api_tempfile} | grep -io "srv:.*" | cut -f2 -d":") local soa=$(cat ${pihole_api_tempfile} | grep -io "soa:.*" | cut -f2 -d":") local ptr=$(cat ${pihole_api_tempfile} | grep -io "ptr:.*" | cut -f2 -d":") local txt=$(cat ${pihole_api_tempfile} | grep -io "txt:.*" | sed 's,},,g' | cut -f2 -d":") echo "NUMBER OF QUERIES BY TYPE IPV4=${ipv4} , IPV6=${ipv6} , ANY=${any} , SRV=${srv} , SOA=${soa} , PTR=${ptr} , TXT=${txt}|IPV4=${ipv4} IPV6=${ipv6} ANY=${any} SRV=${srv} SOA=${soa} PTR=${ptr} TXT=${txt}" } if [ $# -eq 0 ]; then info "usage" exit 1; fi # The options passed by the user while getopts "h:s:iq" opt; do case "$opt" in h ) pihole_ipadd=$OPTARG ;; s ) summary_selected="y" summary_opt=$OPTARG ;; q ) query_type_selected="y" ;; i ) info "version" exit 0 ;; ?) echo "[e] Invalid option. -$OPTARG" exit 1 ;; esac done # The values passed by the user if [ -z ${pihole_ipadd} ]; then echo "[i] Please enter the Pihole IP address as follow: -h pihole_ipaddress"; exit 1; else if [[ "${summary_selected}" == "y" ]]; then # Calling the summary function functSummary exit 1; elif [[ "${query_type_selected}" == "y" ]]; then # Calling the Query Types funct functGetQueryTypes else info "usage" fi # Just delete the temp file rm -f ${pihole_api_tempfile} fi
USAGE
To use this plugin it’s as simple as put in /usr/lib/nagios/plugins or in the default location for your plugins, in my case is the previous one. From here the plugin can be called by Centreon or Nagios.
The usage syntax is the following:
./check_pihole_api -h $PIHOLE_IPADDRESS -s [ clients || queries || ads ] || -i || -q || -t [i] -s (summary) - clients: Number of clients using Pihole as their DNS server - queries: Number of DNS queries - ads: Number and percentage of ads blocked. [i] -i (information) - show the version of the plugin [i] -q - queries by type AAAA, A, SOA, TXT, PTR, ANY, SRV, IPV4, IPV6 [i] -t - Show a TOP number of queries by host
Some examples in my Pi-hole:

Take into account that the values that are being extracted from the API are exactly the same that the values that are show in the Pi-hole Dashboard:

UPDATE 14/04/2020
I have added a new function in order to extract a TOP of number of queries by hosts in the last 24 hours and as you can see it can be graphed:

To get this the plugin has to be executed with the parameter -t:
./check_pihole_api -h $PIHOLE_IPADDRESS -t TOP NUMBER OF QUERIES BY HOST portatil1.pihome=5678 movil1.pihome=4442 movil2.pihome=3556 portatil2.pihome=2280 samsungtv.pihome=1942| portatil1.pihome=5678 movil1.pihome=4442 movil2.pihome=3556 portatil2.pihome=2280 samsungtv.pihome=1942
Hello,
Thx for the script, it’s really usefull to centralize this information in centreon, the implementation is working well in command line, but on in centreon web interface. I thought it was about permissions but i tried a lot of stuff which is not working. It’s like centreon is not interpreting the shell script’s variable. Do you know how to fix this ?
Thx for the help
Hi Yakari,
Could you tell me a bit more about what is happening when you execute the script on Centreon?
As you can see in the post, when i tried it was working fine.
With more information, I’ll help you!
Kind regards
Yakari,
Take into account that the user that is executing the plugins on centreon (nagios/centreon/centreon-engine it depends on you configuration) must have execution, read and write permissions on the folder where plugin it’s located.
Kind regards
Hello,
In Centreon the variable script is not interpreted, but in command line everything is working fine :
in centreon :
Statut détaillé
THERE ARE HOSTS UP & Total=
in command line with centreon user
[centreon@ces ~]$ /usr/lib64/nagios/plugins/check_pihole_api -h 192.168.1.254 -s clients
THERE ARE 9 HOSTS UP & Total=9
Ive connected and tried the execution with the possible different user of centreon : centreon, centreon-engine, centreon-gorgoned) nagios not having /bin/sh , so i modified the /etc/passwd to put /bin/sh and try the execution of the check , but not working. The permission on my folder /usr/lib/centreon/plugin is 777 and i tried to put nagios as owner and group owner, but still nothing. I tried also to execute the plugin a with different path : /usr/lib64/nagios/plugins.
I’m out of solution, the version of my centreon is 20.10.3.
Kind regard