Please upload a debug log and post just the token URL that is generated after the log is uploaded by running the following command from the Pi-hole host terminal:
As I explained, you can fix the settings to use whatever you want.
If you want to use http://192.168.1.254, you just need to disable lighttpd and change Pi-hole port using sudo pihole-FTL --config webserver.port '80o,443os'.
After that, you will be able to use any of these URLs:
Eh… It’s done now. I got the script refactored to show what I want and changed it to use https instead of http.
I spent a couple of hours refactoring the script with the aid of chatgpt (as I suck at coding, and it’s not really my thing). The end result works. So, I’m not going to mess with it now. The thing is, my script worked before. So, what broke it?
This is my newly refactored script:
#!/bin/bash
==========================
Pi-hole Authentication & Stats Monitor
==========================
Configuration
INTERVAL=5 # Network refresh interval (seconds)
SID_EXPIRY=2592000 # SID validity (30 days)
LAN_TARGET="192.168.1.1" # Router IP
WAN_TARGET="1.1.1.1" # Cloudflare DNS
PIHOLE_URL="https://pi.hole:8443" # Pi-hole URL
PIHOLE_PASS_FILE="$HOME/.pihole_auth"
Colors
GREEN="\e[32m"
RED="\e[31m"
YELLOW="\e[33m"
BOLD="\e[1m"
RESET="\e[0m"
Load password
if [[ -f "$PIHOLE_PASS_FILE" ]]; then
PIHOLE_PASS=$(<"$PIHOLE_PASS_FILE")
else
echo -e "${RED}Pi-hole password file not found!${RESET}"
exit 1
fi
Globals
SID=""
CSRF=""
LAST_SID_TIME=0
Get a new SID + CSRF token
get_sid() {
local resp
resp=$(curl -ks -X POST "$PIHOLE_URL/api/auth"
-H "Content-Type: application/json"
-d "{"password":"$PIHOLE_PASS"}")
SID=$(echo "$resp" | jq -r '.session.sid')
CSRF=$(echo "$resp" | jq -r '.session.csrf')
if [[ -z "$SID" || -z "$CSRF" ]]; then
echo -e "${RED}${BOLD}Failed to get SID from Pi-hole.${RESET}"
return 1
fi
return 0
}
Fetch stats
get_stats() {
local stats
stats=$(curl -ks -H "Cookie: sid=$SID" -H "X-CSRF-Token: $CSRF"
"$PIHOLE_URL/api/stats/summary")
if [[ -z "$stats" ]]; then
echo -e "${RED}Failed to fetch Pi-hole stats.${RESET}"
return 1
fi
total=$(echo "$stats" | jq -r '.queries.total')
blocked=$(echo "$stats" | jq -r '.queries.blocked')
percent=$(echo "$stats" | jq -r '.queries.percent_blocked')
echo -e "${BOLD}${GREEN}=== Pi-hole Stats ===${RESET}"
echo -e "${BOLD}Total Queries:${RESET} $total"
echo -e "${BOLD}Blocked Queries:${RESET} $blocked"
echo -e "${BOLD}Percentage Blocked:${RESET} $percent%"
}
Fetch recent queries
get_recent_queries() {
local queries
queries=$(curl -ks -H "Cookie: sid=$SID" -H "X-CSRF-Token: $CSRF"
"$PIHOLE_URL/api/queries")
if [[ -z "$queries" ]]; then
echo -e "${RED}Failed to fetch recent queries.${RESET}"
return 1
fi
echo -e "${BOLD}${GREEN}=== Recent Queries ===${RESET}"
# Extract newest queries first, 10 most recent
echo "$queries" | jq -r '
.queries
| sort_by(.id)
| reverse
| .[]
| "\(.domain) \(.status) \(.client.ip)"' \
| head -n 10 \
| while read domain status client_ip; do
case "$status" in
FORWARDED) echo -e "$domain ($status) [$client_ip]" ;;
CACHE) echo -e "$domain (${YELLOW}$status${RESET}) [$client_ip]" ;;
CACHE_STALE) echo -e "$domain (${YELLOW}$status${RESET}) [$client_ip]" ;;
*) echo -e "$domain (${RED}$status${RESET}) [$client_ip]" ;;
esac
done
}
LAN/WAN checks
check_lan() {
if ping -c1 -W1 "$LAN_TARGET" &>/dev/null; then
echo -e "${BOLD}LAN:${RESET} ${GREEN}UP${RESET}"
else
echo -e "${BOLD}LAN:${RESET} ${RED}DOWN${RESET}"
fi
}
check_wan() {
if ping -c1 -W1 "$WAN_TARGET" &>/dev/null; then
echo -e "${BOLD}WAN:${RESET} ${GREEN}UP${RESET}"
else
echo -e "${BOLD}WAN:${RESET} ${RED}DOWN${RESET}"
fi
}
Recently blocked domains
get_recent_blocked() {
local blocked
blocked=$(curl -ks -H "Cookie: sid=$SID" -H "X-CSRF-Token: $CSRF"
"$PIHOLE_URL/api/stats/recent_blocked")
if [[ -z "$blocked" ]]; then
echo -e "${RED}Failed to fetch blocked domains.${RESET}"
return 1
fi
echo -e "${BOLD}${GREEN}=== Recently Blocked Domains ===${RESET}"
echo "$blocked" | jq -r '.blocked[]' | sort | uniq -c | sort -nr | head -n 10 \
| awk '{print $2 ": " $1}'
}
Main loop
while true; do
clear
echo -e "${BOLD}=== Network & Pi-hole Monitor ===${RESET}"
echo -e "${BOLD}Press Ctrl+C to exit${RESET}\n"
check_lan
check_wan
echo
# Refresh SID if expired
now=$(date +%s)
if [[ -z "$SID" || $((now - LAST_SID_TIME)) -ge $SID_EXPIRY ]]; then
echo -e "${YELLOW}Refreshing Pi-hole SID...${RESET}"
if get_sid; then
LAST_SID_TIME=$now
else
echo -e "${RED}Skipping stats fetch.${RESET}"
fi
fi
get_stats || echo -e "${RED}Stats fetch failed this round.${RESET}"
get_recent_queries || echo -e "${RED}Queried domains fetch failed.${RESET}"
get_recent_blocked || echo -e "${RED}Recently blocked fetch failed.${RESET}"
sleep "$INTERVAL"
done