Files
NetAlertX/plugins/pihole_monitor/index.html
T
2026-10-02 15:51:57 +00:00

6140 lines
113 KiB
HTML

<!DOCTYPE html><html lang="en" class="no-js"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="The main documentation resource for NetAlertX - Network visibility &amp; Asset intelligence application">
<link rel="canonical" href="https://docs.netalertx.com/plugins/pihole_monitor/">
<link rel="prev" href="../pihole_api_scan/">
<link rel="next" href="../pihole_scan/">
<link rel="icon" href="../../img/netalertx_docs.png">
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.21">
<title>Pi-hole Monitor (PIHOLEMON) - Documentation</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.66ac8b77.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&amp;display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../stylesheets/custom.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css">
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<!-- Google Tag Manager -->
<!-- Google tag (gtag.js) -->
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-KCRSGLP8J2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-KCRSGLP8J2');
</script>
<!-- End Google Tag Manager -->
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"><script src="../../assets/javascripts/glightbox.min.js"></script><style id="glightbox-style">
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: white; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color); }
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color); }
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color); }
</style></head>
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="deep-purple">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#pi-hole-monitor-piholemon" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KCRSGLP8J2" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="Documentation" class="md-header__button md-logo" aria-label="Documentation" data-md-component="logo">
<img src="../../img/netalertx_docs.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Documentation
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Pi-hole Monitor (PIHOLEMON)
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="deep-purple" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a7 7 0 0 0-7 7c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-2.26c1.81-1.27 3-3.36 3-5.74a7 7 0 0 0-7-7M9 21a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1H9v1Z"></path></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="deep-purple" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_0" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2a7 7 0 0 1 7 7c0 2.38-1.19 4.47-3 5.74V17a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1v-2.26C6.19 13.47 5 11.38 5 9a7 7 0 0 1 7-7M9 21v-1h6v1a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1m3-17a5 5 0 0 0-5 5c0 2.05 1.23 3.81 3 4.58V16h4v-2.42c1.77-.77 3-2.53 3-4.58a5 5 0 0 0-5-5Z"></path></svg>
</label>
</form>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required="">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard="" data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"></path></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"></path></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix="">
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/netalertx/NetAlertX/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"></path></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../.." class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../INSTALLATION/" class="md-tabs__link">
Installation
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../../SUBNETS/" class="md-tabs__link">
Setup
</a>
</li>
<li class="md-tabs__item">
<a href="../../DEVICE_MANAGEMENT/" class="md-tabs__link">
Device guides
</a>
</li>
<li class="md-tabs__item">
<a href="../../PIHOLE_GUIDE/" class="md-tabs__link">
Other guides
</a>
</li>
<li class="md-tabs__item">
<a href="../../DEBUG_TIPS/" class="md-tabs__link">
Troubleshooting
</a>
</li>
<li class="md-tabs__item">
<a href="../../DEV_ENV_SETUP/" class="md-tabs__link">
Development
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="Documentation" class="md-nav__button md-logo" aria-label="Documentation" data-md-component="logo">
<img src="../../img/netalertx_docs.png" alt="logo">
</a>
Documentation
</label>
<div class="md-nav__source">
<a href="https://github.com/netalertx/NetAlertX/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"></path></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Installation
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Installation
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../INSTALLATION/" class="md-nav__link">
<span class="md-ellipsis">
Installation options
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../INITIAL_SETUP/" class="md-nav__link">
<span class="md-ellipsis">
Quick setup
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_3">
<label class="md-nav__link" for="__nav_2_3" id="__nav_2_3_label" tabindex="0">
<span class="md-ellipsis">
Docker
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_3">
<span class="md-nav__icon md-icon"></span>
Docker
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../DOCKER_INSTALLATION/" class="md-nav__link">
<span class="md-ellipsis">
Docker guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DOCKER_COMPOSE/" class="md-nav__link">
<span class="md-ellipsis">
Docker Compose
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../FILE_PERMISSIONS/" class="md-nav__link">
<span class="md-ellipsis">
Docker file permissions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../UPDATES/" class="md-nav__link">
<span class="md-ellipsis">
Docker updates
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DOCKER_MAINTENANCE/" class="md-nav__link">
<span class="md-ellipsis">
Docker maintenance
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_4">
<label class="md-nav__link" for="__nav_2_4" id="__nav_2_4_label" tabindex="0">
<span class="md-ellipsis">
Docker startup troubleshooting
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_4">
<span class="md-nav__icon md-icon"></span>
Docker startup troubleshooting
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../docker-troubleshooting/arp-flux-sysctls/" class="md-nav__link">
<span class="md-ellipsis">
ARP flux sysctls
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/aufs-capabilities/" class="md-nav__link">
<span class="md-ellipsis">
Aufs capabilities
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/excessive-capabilities/" class="md-nav__link">
<span class="md-ellipsis">
Excessive capabilities
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/file-permissions/" class="md-nav__link">
<span class="md-ellipsis">
File permissions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/incorrect-user/" class="md-nav__link">
<span class="md-ellipsis">
Incorrect user
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/missing-capabilities/" class="md-nav__link">
<span class="md-ellipsis">
Missing capabilities
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/mount-configuration-issues/" class="md-nav__link">
<span class="md-ellipsis">
Mount issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/network-mode/" class="md-nav__link">
<span class="md-ellipsis">
Network mode
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/nginx-configuration-mount/" class="md-nav__link">
<span class="md-ellipsis">
Nginx mount
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/port-conflicts/" class="md-nav__link">
<span class="md-ellipsis">
Port conflicts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/read-only-filesystem/" class="md-nav__link">
<span class="md-ellipsis">
Read only
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../docker-troubleshooting/running-as-root/" class="md-nav__link">
<span class="md-ellipsis">
Running as root
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_5">
<label class="md-nav__link" for="__nav_2_5" id="__nav_2_5_label" tabindex="0">
<span class="md-ellipsis">
Other
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_5">
<span class="md-nav__icon md-icon"></span>
Other
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../SYNOLOGY_GUIDE/" class="md-nav__link">
<span class="md-ellipsis">
Synology guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DOCKER_PORTAINER/" class="md-nav__link">
<span class="md-ellipsis">
Portainer Stacks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../COMMUNITY_GUIDES/" class="md-nav__link">
<span class="md-ellipsis">
Community guides
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../HW_INSTALL/" class="md-nav__link">
<span class="md-ellipsis">
Bare-metal (Experimental)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../MIGRATION/" class="md-nav__link">
<span class="md-ellipsis">
Migration guide
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_6">
<label class="md-nav__link" for="__nav_2_6" id="__nav_2_6_label" tabindex="0">
<span class="md-ellipsis">
Help
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_6">
<span class="md-nav__icon md-icon"></span>
Help
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../COMMON_ISSUES/" class="md-nav__link">
<span class="md-ellipsis">
Common issues
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked="">
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-ellipsis">
Setup
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Setup
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_1" checked="">
<label class="md-nav__link" for="__nav_3_1" id="__nav_3_1_label" tabindex="">
<span class="md-ellipsis">
Getting started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_1">
<span class="md-nav__icon md-icon"></span>
Getting started
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../SUBNETS/" class="md-nav__link">
<span class="md-ellipsis">
Subnets
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_OVERVIEW/" class="md-nav__link">
<span class="md-ellipsis">
Enable Plugins
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_1_3" checked="">
<label class="md-nav__link" for="__nav_3_1_3" id="__nav_3_1_3_label" tabindex="0">
<span class="md-ellipsis">
Plugins reference
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_3_1_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_1_3">
<span class="md-nav__icon md-icon"></span>
Plugins reference
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../_publisher_apprise/" class="md-nav__link">
<span class="md-ellipsis">
Apprise publisher (APPRISE)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_email/" class="md-nav__link">
<span class="md-ellipsis">
Email publisher (SMTP) (SMTP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_mqtt/" class="md-nav__link">
<span class="md-ellipsis">
MQTT publisher (MQTT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_ntfy/" class="md-nav__link">
<span class="md-ellipsis">
NTFY publisher (NTFY)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_pushover/" class="md-nav__link">
<span class="md-ellipsis">
Pushover publisher (PUSHOVER)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_pushsafer/" class="md-nav__link">
<span class="md-ellipsis">
Pushsafer publisher (PUSHSAFER)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_telegram/" class="md-nav__link">
<span class="md-ellipsis">
Telegram publisher (TELEGRAM)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../_publisher_webhook/" class="md-nav__link">
<span class="md-ellipsis">
Webhook publisher (WEBHOOK)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adguard_export/" class="md-nav__link">
<span class="md-ellipsis">
AdGuard (Device Export) (ADGUARDEXP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adguard_import/" class="md-nav__link">
<span class="md-ellipsis">
AdGuard (Device import) (ADGUARDIMP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../arp_scan/" class="md-nav__link">
<span class="md-ellipsis">
Arp-Scan (Network scan) (ARPSCAN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../asuswrt_import/" class="md-nav__link">
<span class="md-ellipsis">
AsusWRT device import (ASUSWRT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../avahi_scan/" class="md-nav__link">
<span class="md-ellipsis">
AVAHISCAN (Naming) (AVAHISCAN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../csv_backup/" class="md-nav__link">
<span class="md-ellipsis">
CSV backup (CSVBCKP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../custom_props/" class="md-nav__link">
<span class="md-ellipsis">
Custom properties (CUSTPROP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../db_cleanup/" class="md-nav__link">
<span class="md-ellipsis">
DB cleanup (DBCLNP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ddns_update/" class="md-nav__link">
<span class="md-ellipsis">
DDNS update (DDNS)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp_leases/" class="md-nav__link">
<span class="md-ellipsis">
DHCP Leases (Device import) (DHCPLSS)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp_leases/ASUS_ROUTERS/" class="md-nav__link">
<span class="md-ellipsis">
Configuring the DHCPLSS plugin to import clients from the YazFi plugin
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp_servers/" class="md-nav__link">
<span class="md-ellipsis">
Rogue DHCP (DHCPSRVS)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dig_scan/" class="md-nav__link">
<span class="md-ellipsis">
Dig (Name resolution) (DIGSCAN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dockerdisc/" class="md-nav__link">
<span class="md-ellipsis">
Docker discovery (DOCKERDISC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../freebox/" class="md-nav__link">
<span class="md-ellipsis">
Freebox (FREEBOX)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../fritzbox/" class="md-nav__link">
<span class="md-ellipsis">
FRITZ!Box (FRITZBOX)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../icmp_scan/" class="md-nav__link">
<span class="md-ellipsis">
ICMP (Status check) (ICMP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../internet_ip/" class="md-nav__link">
<span class="md-ellipsis">
Internet check (INTRNT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../internet_speedtest/" class="md-nav__link">
<span class="md-ellipsis">
Internet speedtest (INTRSPD)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ipneigh/" class="md-nav__link">
<span class="md-ellipsis">
IP Neigh (IPNEIGH)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../kea_api/" class="md-nav__link">
<span class="md-ellipsis">
Kea DHCP API (KEALSS)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../luci_import/" class="md-nav__link">
<span class="md-ellipsis">
Luci rpc import (Device import) (LUCIRPC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../maintenance/" class="md-nav__link">
<span class="md-ellipsis">
Maintenance (MAINT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../mikrotik_scan/" class="md-nav__link">
<span class="md-ellipsis">
Mikrotik (Device discovery) (MTSCAN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nbtscan_scan/" class="md-nav__link">
<span class="md-ellipsis">
NBTSCAN (Naming) (NBTSCAN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../newdev_template/" class="md-nav__link">
<span class="md-ellipsis">
New Devices (NEWDEV)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nmap_dev_scan/" class="md-nav__link">
<span class="md-ellipsis">
NMAP Device discovery (NMAPDEV)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nmap_scan/" class="md-nav__link">
<span class="md-ellipsis">
Services &amp; Ports (NMAP) (NMAP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../notification_processing/" class="md-nav__link">
<span class="md-ellipsis">
Notification Processing (NTFPRCS)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nslookup_scan/" class="md-nav__link">
<span class="md-ellipsis">
NSLOOKUP (Naming) (NSLOOKUP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../omada_sdn_imp/" class="md-nav__link">
<span class="md-ellipsis">
OMADA SDN import (do not use) (OMDSDN)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../omada_sdn_openapi/" class="md-nav__link">
<span class="md-ellipsis">
Omada SDN using OpenAPI (OMDSDNOPENAPI)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../pihole_api_scan/" class="md-nav__link">
<span class="md-ellipsis">
PiHole API scan (PIHOLEAPI)
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Pi-hole Monitor (PIHOLEMON)
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Pi-hole Monitor (PIHOLEMON)
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#overview-piholemon-plugin-pi-hole-monitor" class="md-nav__link">
<span class="md-ellipsis">
Overview - PIHOLEMON Plugin — Pi-hole Monitor
</span>
</a>
<nav class="md-nav" aria-label="Overview - PIHOLEMON Plugin — Pi-hole Monitor">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#why-not-just-run-two-copies-of-piholeapi-for-two-pi-holes" class="md-nav__link">
<span class="md-ellipsis">
Why not just run two copies of PIHOLEAPI for two Pi-holes?
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#quick-setup-guide" class="md-nav__link">
<span class="md-ellipsis">
Quick setup guide
</span>
</a>
<nav class="md-nav" aria-label="Quick setup guide">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a-note-on-http-vs-https" class="md-nav__link">
<span class="md-ellipsis">
🔒 A note on http:// vs https://
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#usage" class="md-nav__link">
<span class="md-ellipsis">
Usage
</span>
</a>
<nav class="md-nav" aria-label="Usage">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a-note-on-the-blocked-query-count-per-run-delta-not-a-running-total" class="md-nav__link">
<span class="md-ellipsis">
A note on the blocked-query count: per-run delta, not a running total
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#testing-the-notification-pipeline-end-to-end" class="md-nav__link">
<span class="md-ellipsis">
Testing the notification pipeline end-to-end
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#troubleshooting" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Troubleshooting
</span>
</a>
<nav class="md-nav" aria-label="⚠️ Troubleshooting">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#authentication-failed-no-data-from-a-pi-hole-instance" class="md-nav__link">
<span class="md-ellipsis">
❌ Authentication failed / no data from a Pi-hole instance
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#some-devices-are-missing" class="md-nav__link">
<span class="md-ellipsis">
❌ Some devices are missing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#notifications-dont-arrive-even-though-an-anomaly-was-detected" class="md-nav__link">
<span class="md-ellipsis">
❌ Notifications don't arrive even though an anomaly was detected
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#anomaly-label-missing-an-owner" class="md-nav__link">
<span class="md-ellipsis">
❌ Anomaly label missing an owner
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#getting-flagged-for-normal-usage-not-getting-flagged-for-a-real-spike" class="md-nav__link">
<span class="md-ellipsis">
❌ Getting flagged for normal usage / not getting flagged for a real spike
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#notes" class="md-nav__link">
<span class="md-ellipsis">
Notes
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../pihole_scan/" class="md-nav__link">
<span class="md-ellipsis">
PiHole (Device sync) (PIHOLE)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../rest_import/" class="md-nav__link">
<span class="md-ellipsis">
REST Import (RSTIMPRT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../set_password/" class="md-nav__link">
<span class="md-ellipsis">
Set password (SETPWD)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../snmp_discovery/" class="md-nav__link">
<span class="md-ellipsis">
SNMP discovery (SNMPDSC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../sync/" class="md-nav__link">
<span class="md-ellipsis">
Sync Hub (SYNC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ui_settings/" class="md-nav__link">
<span class="md-ellipsis">
UI Settings (UI)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../unifi_api_import/" class="md-nav__link">
<span class="md-ellipsis">
UniFi import (API) (UNIFIAPI)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../unifi_import/" class="md-nav__link">
<span class="md-ellipsis">
UniFi import (UNFIMP)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vendor_update/" class="md-nav__link">
<span class="md-ellipsis">
Vendor update (VNDRPDT)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../wake_on_lan/" class="md-nav__link">
<span class="md-ellipsis">
Wake on Lan (WOL) (WOL)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../website_monitor/" class="md-nav__link">
<span class="md-ellipsis">
Services &amp; Web monitor (WEBMON)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../wificanary/" class="md-nav__link">
<span class="md-ellipsis">
WiFi Canary (WIFICANARY)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../workflows/" class="md-nav__link">
<span class="md-ellipsis">
Workflows (WORKFLOWS)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../BACKUPS/" class="md-nav__link">
<span class="md-ellipsis">
Backups
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../SECURITY_FEATURES/" class="md-nav__link">
<span class="md-ellipsis">
Security features
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../SECURITY/" class="md-nav__link">
<span class="md-ellipsis">
Security considerations
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_2">
<label class="md-nav__link" for="__nav_3_2" id="__nav_3_2_label" tabindex="">
<span class="md-ellipsis">
Advanced guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_2">
<span class="md-nav__icon md-icon"></span>
Advanced guides
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../REMOTE_NETWORKS/" class="md-nav__link">
<span class="md-ellipsis">
Remote networks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../NOTIFICATIONS/" class="md-nav__link">
<span class="md-ellipsis">
Notifications guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../NOTIFICATION_TEMPLATES/" class="md-nav__link">
<span class="md-ellipsis">
Notification text templates
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PUID_PGID_SECURITY/" class="md-nav__link">
<span class="md-ellipsis">
Custom PUID/GUID
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../NAME_RESOLUTION/" class="md-nav__link">
<span class="md-ellipsis">
Name resolution
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../AUTHELIA/" class="md-nav__link">
<span class="md-ellipsis">
Authelia guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PERFORMANCE/" class="md-nav__link">
<span class="md-ellipsis">
Performance guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../REVERSE_DNS/" class="md-nav__link">
<span class="md-ellipsis">
Reverse DNS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../REVERSE_PROXY/" class="md-nav__link">
<span class="md-ellipsis">
Reverse proxy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../WORKFLOWS/" class="md-nav__link">
<span class="md-ellipsis">
Workflows
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../WORKFLOW_EXAMPLES/" class="md-nav__link">
<span class="md-ellipsis">
Workflow examples
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DOCKER_SWARM/" class="md-nav__link">
<span class="md-ellipsis">
Docker Swarm
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3">
<label class="md-nav__link" for="__nav_3_3" id="__nav_3_3_label" tabindex="">
<span class="md-ellipsis">
Best practice guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Best practice guides
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../ADVISORY_EYES_ON_GLASS/" class="md-nav__link">
<span class="md-ellipsis">
NOC / Eyes-on-glass dashboard
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../ADVISORY_MULTI_NETWORK/" class="md-nav__link">
<span class="md-ellipsis">
Multi-network (VLAN / routing) monitoring
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../ADVISORY_MULTI_SITE_MONITORING/" class="md-nav__link">
<span class="md-ellipsis">
Multi-site (MSP / customer / branch) monitoring
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_4">
<label class="md-nav__link" for="__nav_3_4" id="__nav_3_4_label" tabindex="">
<span class="md-ellipsis">
Help
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_4">
<span class="md-nav__icon md-icon"></span>
Help
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../COMMON_ISSUES/" class="md-nav__link">
<span class="md-ellipsis">
Common issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../RANDOM_MAC/" class="md-nav__link">
<span class="md-ellipsis">
Random MAC
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4">
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Device guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Device guides
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_1">
<label class="md-nav__link" for="__nav_4_1" id="__nav_4_1_label" tabindex="0">
<span class="md-ellipsis">
Editing devices
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_1">
<span class="md-nav__icon md-icon"></span>
Editing devices
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../DEVICE_MANAGEMENT/" class="md-nav__link">
<span class="md-ellipsis">
Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICES_BULK_EDITING/" class="md-nav__link">
<span class="md-ellipsis">
Bulk editing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../CUSTOM_PROPERTIES/" class="md-nav__link">
<span class="md-ellipsis">
Custom properties
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_DISPLAY_SETTINGS/" class="md-nav__link">
<span class="md-ellipsis">
Device display settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_FILTERS/" class="md-nav__link">
<span class="md-ellipsis">
Device views filtering
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../SESSION_INFO/" class="md-nav__link">
<span class="md-ellipsis">
Session info
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_FIELD_LOCK/" class="md-nav__link">
<span class="md-ellipsis">
Field Lock/Unlock
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_2">
<label class="md-nav__link" for="__nav_4_2" id="__nav_4_2_label" tabindex="0">
<span class="md-ellipsis">
Device auditing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_2">
<span class="md-nav__icon md-icon"></span>
Device auditing
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../DEVICE_CHANGE_LOG/" class="md-nav__link">
<span class="md-ellipsis">
Change log
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_PRESENCE/" class="md-nav__link">
<span class="md-ellipsis">
Presence
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_SOURCE_FIELDS/" class="md-nav__link">
<span class="md-ellipsis">
Device source fields
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_3">
<label class="md-nav__link" for="__nav_4_3" id="__nav_4_3_label" tabindex="0">
<span class="md-ellipsis">
Icons and network topology
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_3">
<span class="md-nav__icon md-icon"></span>
Icons and network topology
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../ICONS/" class="md-nav__link">
<span class="md-ellipsis">
Icons
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../NETWORK_TREE/" class="md-nav__link">
<span class="md-ellipsis">
Network topology
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Other guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Other guides
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../PIHOLE_GUIDE/" class="md-nav__link">
<span class="md-ellipsis">
Pi-hole guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../HOME_ASSISTANT/" class="md-nav__link">
<span class="md-ellipsis">
Home Assistant
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../SMTP/" class="md-nav__link">
<span class="md-ellipsis">
Common email services
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../REST_IMPORT/" class="md-nav__link">
<span class="md-ellipsis">
Rest import
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../WEBHOOK_N8N/" class="md-nav__link">
<span class="md-ellipsis">
Webhooks (n8n)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
Troubleshooting
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Troubleshooting
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../DEBUG_TIPS/" class="md-nav__link">
<span class="md-ellipsis">
General tips
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../COMMON_ISSUES/" class="md-nav__link">
<span class="md-ellipsis">
Common issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../LOGGING/" class="md-nav__link">
<span class="md-ellipsis">
Inspecting logs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEBUG_API_SERVER/" class="md-nav__link">
<span class="md-ellipsis">
API server issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEBUG_INVALID_JSON/" class="md-nav__link">
<span class="md-ellipsis">
Invalid JSON issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEBUG_PHP/" class="md-nav__link">
<span class="md-ellipsis">
PHP backend issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEBUG_PLUGINS/" class="md-nav__link">
<span class="md-ellipsis">
Plugin issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../WEB_UI_PORT_DEBUG/" class="md-nav__link">
<span class="md-ellipsis">
Web UI port issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../WORKFLOWS_DEBUGGING/" class="md-nav__link">
<span class="md-ellipsis">
Workflows issues
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../FIX_OFFLINE_DETECTION/" class="md-nav__link">
<span class="md-ellipsis">
Incorrect offline detection
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7">
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Development
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Development
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7_1">
<label class="md-nav__link" for="__nav_7_1" id="__nav_7_1_label" tabindex="0">
<span class="md-ellipsis">
Plugin and app development
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_1">
<span class="md-nav__icon md-icon"></span>
Plugin and app development
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../DEV_ENV_SETUP/" class="md-nav__link">
<span class="md-ellipsis">
Environment setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../BUILDS/" class="md-nav__link">
<span class="md-ellipsis">
Builds
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEV_DEVCONTAINER/" class="md-nav__link">
<span class="md-ellipsis">
Devcontainer
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEV_PORTS_HOST_MODE/" class="md-nav__link">
<span class="md-ellipsis">
Devcontainer ports
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7_1_5">
<label class="md-nav__link" for="__nav_7_1_5" id="__nav_7_1_5_label" tabindex="0">
<span class="md-ellipsis">
Custom plugins
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_7_1_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_1_5">
<span class="md-nav__icon md-icon"></span>
Custom plugins
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../PLUGINS_DEV/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_QUICK_START/" class="md-nav__link">
<span class="md-ellipsis">
Quick start
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_DATA_CONTRACT/" class="md-nav__link">
<span class="md-ellipsis">
Data contract
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_IMPORT_BEHAVIOR/" class="md-nav__link">
<span class="md-ellipsis">
Import behavior
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_SETTINGS/" class="md-nav__link">
<span class="md-ellipsis">
Settings system
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_DATASOURCES/" class="md-nav__link">
<span class="md-ellipsis">
Data sources
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_UI_COMPONENTS/" class="md-nav__link">
<span class="md-ellipsis">
UI components
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../PLUGINS_DEV_CONFIG/" class="md-nav__link">
<span class="md-ellipsis">
Config lifecycle
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../FRONTEND_DEVELOPMENT/" class="md-nav__link">
<span class="md-ellipsis">
Frontend development
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DATABASE/" class="md-nav__link">
<span class="md-ellipsis">
Database
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../SETTINGS_SYSTEM/" class="md-nav__link">
<span class="md-ellipsis">
Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../VERSIONS/" class="md-nav__link">
<span class="md-ellipsis">
Versions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../DEVICE_HEURISTICS/" class="md-nav__link">
<span class="md-ellipsis">
Icon and type guessing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7_2">
<label class="md-nav__link" for="__nav_7_2" id="__nav_7_2_label" tabindex="0">
<span class="md-ellipsis">
API
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_2">
<span class="md-nav__icon md-icon"></span>
API
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../API/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_DEVICES/" class="md-nav__link">
<span class="md-ellipsis">
Devices collection
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_DEVICE/" class="md-nav__link">
<span class="md-ellipsis">
Device
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_DEVICE_FIELD_LOCK/" class="md-nav__link">
<span class="md-ellipsis">
Device field Lock
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_SESSIONS/" class="md-nav__link">
<span class="md-ellipsis">
Sessions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_SETTINGS/" class="md-nav__link">
<span class="md-ellipsis">
Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_EVENTS/" class="md-nav__link">
<span class="md-ellipsis">
Events
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_MESSAGING_IN_APP/" class="md-nav__link">
<span class="md-ellipsis">
Messaging in-app
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_METRICS/" class="md-nav__link">
<span class="md-ellipsis">
Metrics
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_NETTOOLS/" class="md-nav__link">
<span class="md-ellipsis">
Net tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_ONLINEHISTORY/" class="md-nav__link">
<span class="md-ellipsis">
Online history
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_SYNC/" class="md-nav__link">
<span class="md-ellipsis">
Sync
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_LOGS/" class="md-nav__link">
<span class="md-ellipsis">
Logs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_SSE/" class="md-nav__link">
<span class="md-ellipsis">
SSE
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_GRAPHQL/" class="md-nav__link">
<span class="md-ellipsis">
GraphQL
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_DBQUERY/" class="md-nav__link">
<span class="md-ellipsis">
DB query
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_MCP/" class="md-nav__link">
<span class="md-ellipsis">
MCP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_TESTS/" class="md-nav__link">
<span class="md-ellipsis">
Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../API_OLD/" class="md-nav__link">
<span class="md-ellipsis">
SUPERSEDED OLD API Overview
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7_3">
<label class="md-nav__link" for="__nav_7_3" id="__nav_7_3_label" tabindex="0">
<span class="md-ellipsis">
Integrations
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_3">
<span class="md-nav__icon md-icon"></span>
Integrations
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../../WEBHOOK_SECRET/" class="md-nav__link">
<span class="md-ellipsis">
Webhook secret
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../HELPER_SCRIPTS/" class="md-nav__link">
<span class="md-ellipsis">
Helper scripts
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#overview-piholemon-plugin-pi-hole-monitor" class="md-nav__link">
<span class="md-ellipsis">
Overview - PIHOLEMON Plugin — Pi-hole Monitor
</span>
</a>
<nav class="md-nav" aria-label="Overview - PIHOLEMON Plugin — Pi-hole Monitor">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#why-not-just-run-two-copies-of-piholeapi-for-two-pi-holes" class="md-nav__link">
<span class="md-ellipsis">
Why not just run two copies of PIHOLEAPI for two Pi-holes?
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#quick-setup-guide" class="md-nav__link">
<span class="md-ellipsis">
Quick setup guide
</span>
</a>
<nav class="md-nav" aria-label="Quick setup guide">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a-note-on-http-vs-https" class="md-nav__link">
<span class="md-ellipsis">
🔒 A note on http:// vs https://
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#usage" class="md-nav__link">
<span class="md-ellipsis">
Usage
</span>
</a>
<nav class="md-nav" aria-label="Usage">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a-note-on-the-blocked-query-count-per-run-delta-not-a-running-total" class="md-nav__link">
<span class="md-ellipsis">
A note on the blocked-query count: per-run delta, not a running total
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#testing-the-notification-pipeline-end-to-end" class="md-nav__link">
<span class="md-ellipsis">
Testing the notification pipeline end-to-end
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#troubleshooting" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Troubleshooting
</span>
</a>
<nav class="md-nav" aria-label="⚠️ Troubleshooting">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#authentication-failed-no-data-from-a-pi-hole-instance" class="md-nav__link">
<span class="md-ellipsis">
❌ Authentication failed / no data from a Pi-hole instance
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#some-devices-are-missing" class="md-nav__link">
<span class="md-ellipsis">
❌ Some devices are missing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#notifications-dont-arrive-even-though-an-anomaly-was-detected" class="md-nav__link">
<span class="md-ellipsis">
❌ Notifications don't arrive even though an anomaly was detected
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#anomaly-label-missing-an-owner" class="md-nav__link">
<span class="md-ellipsis">
❌ Anomaly label missing an owner
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#getting-flagged-for-normal-usage-not-getting-flagged-for-a-real-spike" class="md-nav__link">
<span class="md-ellipsis">
❌ Getting flagged for normal usage / not getting flagged for a real spike
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#notes" class="md-nav__link">
<span class="md-ellipsis">
Notes
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/netalertx/NetAlertX/blob/main/server/plugins/pihole_monitor/README.md" title="Edit this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4v-2m10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1 2.1 2.1Z"></path></svg>
</a>
<a href="https://github.com/netalertx/NetAlertX/raw/main/server/plugins/pihole_monitor/README.md" title="View source of this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.15 8.15 0 0 1-1.23-2Z"></path></svg>
</a>
<h1 id="pi-hole-monitor-piholemon">Pi-hole Monitor (PIHOLEMON)</h1>
<div class="admonition note">
<p class="admonition-title">Generated page</p>
<p>This page mirrors <a href="https://github.com/netalertx/NetAlertX/blob/main/server/plugins/pihole_monitor/README.md"><code>server/plugins/pihole_monitor/README.md</code></a> and is regenerated on every docs build.</p>
</div>
<h2 id="overview-piholemon-plugin-pi-hole-monitor">Overview - PIHOLEMON Plugin — Pi-hole Monitor</h2>
<p>The <strong>PIHOLEMON</strong> plugin does two jobs against the same Pi-hole connection(s):</p>
<ol>
<li><strong>Query anomaly detection</strong> - flags a device whose <em>blocked</em>-query count spikes well above its own recent average, the classic signature of malware or a compromised device beaconing out to blocklisted domains. This is deliberately not the same thing as device discovery: it's about a device you already know suddenly behaving differently, not a new device showing up.</li>
<li><strong>Device import</strong> - same job as the official <strong>PIHOLEAPI</strong> (<code>pihole_api_scan</code>) plugin: pulls the device list from Pi-hole and feeds it into NetAlertX's normal device-scanner pipeline, so a device Pi-hole knows about but NetAlertX doesn't gets created automatically.</li>
</ol>
<p>Both share one login per Pi-hole instance and one settings page, instead of being two separately configured pieces that happen to need the same credentials.</p>
<p>See the <a href="https://docs.netalertx.com/PIHOLE_GUIDE">Pi-hole guide</a> for a walkthrough covering this plugin alongside the other Pi-hole integrations (<code>PIHOLE</code>, <code>PIHOLEAPI</code>, <code>DHCPLSS</code>).</p>
<p>Two design choices worth knowing about:</p>
<ul>
<li><strong>Both a primary and an optional secondary/failover Pi-hole are checked, and their results combined.</strong> Watching only one leaves an obvious blind spot for the anomaly detection - a device can simply point at the other resolver and never show up. Leave the secondary URL blank if you only run one Pi-hole; most setups do.</li>
<li><strong>The anomaly baseline is keyed by MAC address, not IP.</strong> DHCP-assigned IPs change; since this plugin already has the device list from Pi-hole itself, it resolves IP to MAC from that same data - no separate lookup needed for that part. A device owner, if you use NetAlertX's <code>devOwner</code> field, is looked up via NetAlertX's own GraphQL API purely to make the anomaly label friendlier; it's optional and never blocks import or detection if unavailable.</li>
</ul>
<h3 id="why-not-just-run-two-copies-of-piholeapi-for-two-pi-holes">Why not just run two copies of PIHOLEAPI for two Pi-holes?</h3>
<p>PIHOLEAPI doesn't support running two independent instances against different Pi-holes - both copies would read and write the same settings keys. PIHOLEMON was built to support a primary and secondary instance natively from the start.</p>
<h3 id="quick-setup-guide">Quick setup guide</h3>
<ul>
<li>You are running <strong>Pi-hole v6</strong> or newer on every instance you configure (this plugin uses <code>/api/auth</code>, <code>/api/network/devices</code>, and <code>/api/stats/top_clients</code>, none of which exist in v5).</li>
<li>An <strong>App Password</strong> is generated on each Pi-hole (<code>Settings → Web Interface / API → App Password</code>) - recommended over using the admin login password directly.</li>
<li>Like every non-core plugin, <strong>When to run</strong> (<code>PIHOLEMON_RUN</code>) defaults to <code>disabled</code> - set it to <code>schedule</code> (or another option) once your URL/password are filled in, or nothing runs.</li>
</ul>
<h4 id="a-note-on-http-vs-https">🔒 A note on <code>http://</code> vs <code>https://</code></h4>
<p>Most home Pi-hole setups (including the one this plugin was developed and tested against) run over plain <code>http://</code> on a trusted LAN, and that's what the examples below use - this plugin doesn't require <code>https://</code> or refuse an <code>http://</code> URL. Know the trade-off either way, though: over <code>http://</code>, the App Password/admin password is sent in cleartext on every run, readable by anything else that can see that network segment (a compromised device, a hostile guest network, etc.). If your Pi-hole's admin interface is reachable from anywhere less trusted than your own LAN, either put it behind <code>https://</code> (Pi-hole's own self-signed cert, or a reverse proxy with a real one) or keep it LAN-only. <strong>Verify SSL</strong> only matters once an instance is on <code>https://</code> - it's on by default, per instance (primary and secondary can each be on <code>http://</code> or <code>https://</code> independently), and turning it off to tolerate a self-signed cert accepts <em>any</em> certificate, including an attacker's; installing that self-signed CA as trusted on the machine running NetAlertX is the safer way to use a self-signed cert if you need one.</p>
<h3 id="usage">Usage</h3>
<ul>
<li>Head to <strong>Settings</strong> &gt; <strong>Pi-hole Monitor</strong> to fill in the values below.</li>
</ul>
<table>
<thead>
<tr>
<th>Setting Key</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>PIHOLEMON_PRIMARY_URL</strong></td>
<td>Required. URL to your primary Pi-hole, e.g. <code>http://192.168.1.10/</code>.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_PRIMARY_PASSWORD</strong></td>
<td>App Password (or admin password) for the primary Pi-hole.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_PRIMARY_VERIFY_SSL</strong></td>
<td>Verify TLS certificates on the <em>primary</em> instance's <code>https://</code> URL. Default <strong>on</strong>. Only disable if that Pi-hole uses a self-signed certificate you can't install as trusted - see the security note below.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_SECONDARY_URL</strong></td>
<td>Optional. URL to a secondary/failover Pi-hole, e.g. <code>http://192.168.1.11:8080/</code>. Leave blank if you only run one.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_SECONDARY_PASSWORD</strong></td>
<td>Only used if a secondary URL is set.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_SECONDARY_VERIFY_SSL</strong></td>
<td>Same, for the <em>secondary</em> instance. Only used if a secondary URL is set. Default <strong>on</strong>.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_GET_OFFLINE</strong></td>
<td>Import devices even if not recently seen. Default off.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_CONSIDER_ONLINE</strong></td>
<td>Seconds since last seen to still count a device as online. Default <code>300</code>.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_API_MAXCLIENTS</strong></td>
<td>Maximum devices requested <strong>per instance</strong>'s device list. Default <code>500</code>.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_FAKE_MAC</strong></td>
<td>Generate a fake MAC from the IP for devices with a non-standard hardware address. Default off.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_GET_OWNER</strong></td>
<td>Look up an already-known device's owner for a friendlier anomaly label. Default <strong>on</strong>. Uses this app's own <strong>GRAPHQL_PORT</strong> and <strong>API_TOKEN</strong> settings (Settings → General) automatically - nothing else to configure. Disable if you don't use device owners.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_MULTIPLIER</strong></td>
<td>Flag a device when the blocked queries it generated <em>since the last run</em> exceed this many times its own recent per-run average. Default <code>4</code>.</td>
</tr>
<tr>
<td><strong>PIHOLEMON_MIN_BLOCKED</strong></td>
<td>Ignore devices below this many blocked queries since the last run, even if the multiplier is exceeded. Default <code>20</code> - depends heavily on your Schedule (see the note below the settings table).</td>
</tr>
<tr>
<td><strong>PIHOLEMON_HISTORY_DAYS</strong></td>
<td>How many days of recent runs to keep per device for the rolling baseline. A real time window, not a sample count - means the same thing regardless of your Schedule setting, and a faster schedule just adds more data points inside it. Default <code>7</code> (one week).</td>
</tr>
<tr>
<td><strong>Watched</strong> <em>(standard NetAlertX setting)</em></td>
<td>Which columns count as "changed" for notification purposes. Defaults to <code>watchedValue4</code> (the anomaly/normal flag) only - the per-run blocked-query delta changes every run by design.</td>
</tr>
</tbody>
</table>
<h4 id="a-note-on-the-blocked-query-count-per-run-delta-not-a-running-total">A note on the blocked-query count: per-run delta, not a running total</h4>
<p>Pi-hole's <code>/api/stats/top_clients</code> returns a count that's cumulative since Pi-hole's FTL service last started - it does not reset daily, and it's not a "since I last checked" delta. This plugin diffs each run's raw count against the one from its last run to get a real per-run increment, which is what <code>PIHOLEMON_MULTIPLIER</code>/<code>PIHOLEMON_MIN_BLOCKED</code> actually compare against - comparing the raw cumulative totals directly would make any device's traffic look like a growing "anomaly" purely from the counter never resetting. The very first run for a device, and any run right after Pi-hole/FTL restarts (the counter resets, so the raw count can drop below what was last seen), can't produce a valid delta - those runs establish a new reference point instead of evaluating an anomaly.
| <strong>Report on</strong> <em>(standard NetAlertX setting)</em> | Which statuses actually notify. Defaults to <code>watched-changed</code> only, so you hear about it exactly when a device flips into (or out of) an anomaly. |</p>
<p>This plugin does <strong>not</strong> send notifications on its own - it relies on NetAlertX's own core, which diffs the columns picked in <strong>Watched</strong> between runs and, on a match against <strong>Report on</strong>, dispatches through whichever publisher(s) you already have enabled under <strong>Settings → Notifications</strong> (ntfy, Apprise, email, Telegram, ...).</p>
<p>One extra setting is required for that to actually reach you: NetAlertX's <strong>Notification Processing</strong> plugin (<code>NTFPRCS</code>) has its own <strong>"Notify on"</strong> setting (<code>NTFPRCS_INCLUDED_SECTIONS</code>), and its default value - <code>new_devices</code>, <code>down_devices</code>, <code>events</code> - does <strong>not</strong> include <code>plugins</code>. Without <code>plugins</code> in that list, this plugin's Watched/Report on matches are recorded correctly but never make it into a notification. Add <code>plugins</code> to <code>NTFPRCS_INCLUDED_SECTIONS</code> once, and it also covers any other plugin using the same mechanism, not just this one.</p>
<p>The default text notification for the <code>plugins</code> section is a generic vertical <code>Header: Value</code> dump. For something more readable, set <code>NTFPRCS</code>'s <strong>"Text Template: Plugins"</strong> (<code>NTFPRCS_TEXT_TEMPLATE_plugins</code>) to something like:</p>
<div class="highlight"><pre><span></span><code>{objectPrimaryId} [{watchedValue2}] @ {objectSecondaryId} → {watchedValue4} ({watchedValue3} blocked)
</code></pre></div>
<p>Only the columns the <code>plugins</code> section actually selects are available as placeholders (<code>{plugin}</code>, <code>{objectPrimaryId}</code>, <code>{objectSecondaryId}</code>, <code>{dateTimeChanged}</code>, <code>{watchedValue1-4}</code>, <code>{status}</code>) - <code>extra</code> (where this plugin's <code>owner</code>/<code>ratio</code> detail lives) isn't one of them, so that richer text is only visible on the device's page in NetAlertX, not in the notification itself. This template setting is global to <code>NTFPRCS</code>, so it affects any plugin using Watched/Report on, not just this one.</p>
<p>If the same device (same MAC) is seen on both instances, the entry with the more recent "last seen" timestamp wins - it isn't imported twice, and its blocked-query counts from both instances are summed, not compared separately.</p>
<h3 id="testing-the-notification-pipeline-end-to-end">Testing the notification pipeline end-to-end</h3>
<p>Waiting for real, organic beaconing traffic to confirm notifications actually arrive isn't practical. The clean way to force a <code>normal</code> → <code>anomaly</code> transition on demand, without touching any internal state file by hand:</p>
<ol>
<li>Temporarily set <code>PIHOLEMON_MULTIPLIER</code> to something like <code>1.01</code> and <code>PIHOLEMON_MIN_BLOCKED</code> to <code>1</code>.</li>
<li>Run the plugin (wait for its schedule, or trigger it manually from the UI).</li>
<li>Any device with a baseline and <em>any</em> blocked traffic should now flip to <code>anomaly</code> - confirming the whole chain: Watched/Report on match → <code>Plugins_Events</code> row → NetAlertX's Notification Processing (<code>NTFPRCS</code>, needs <code>plugins</code> in <code>NTFPRCS_INCLUDED_SECTIONS</code>, see above) → your configured publisher.</li>
<li>Set <code>PIHOLEMON_MULTIPLIER</code>/<code>PIHOLEMON_MIN_BLOCKED</code> back to their real values afterward - left at the test values, everything with any traffic at all reads as an anomaly.</li>
</ol>
<h3 id="troubleshooting">⚠️ Troubleshooting</h3>
<hr>
<h4 id="authentication-failed-no-data-from-a-pi-hole-instance">❌ Authentication failed / no data from a Pi-hole instance</h4>
<ul>
<li>Confirm the URL includes the scheme (<code>http://</code>/<code>https://</code>) and, if not on the default port, the port too - e.g. <code>http://192.168.1.10/</code> ✔, <code>http://192.168.1.10/admin</code> ❌.</li>
<li>Confirm that instance is running <strong>Pi-hole v6</strong>, not v5.</li>
<li>SSL verification matches your setup (disable for self-signed certificates).</li>
<li>Try the App Password by hand first: <code>curl -X POST &lt;url&gt;/api/auth -d '{"password":"&lt;app password&gt;"}'</code> should return a <code>session.sid</code>.</li>
<li>Check the plugin log for <code>[PIHOLEMON] &lt;label&gt;: ...</code> lines - <code>label</code> is <code>primary</code> or <code>secondary</code>, so you can tell which instance is the problem.</li>
</ul>
<hr>
<h4 id="some-devices-are-missing">❌ Some devices are missing</h4>
<ul>
<li>Devices with an invalid MAC are skipped unless <strong>Generate fake MAC</strong> is enabled - turning it on trades data consistency for coverage (the "MAC" becomes a stand-in derived from the IP, not a real hardware address).</li>
<li>Offline devices don't get a device-import row (name/vendor) unless <strong>Import offline devices</strong> is enabled - but their MAC is still used to attribute blocked-query counts correctly, so an offline-but-active device never falls back to being tracked by bare IP.</li>
</ul>
<hr>
<h4 id="notifications-dont-arrive-even-though-an-anomaly-was-detected">❌ Notifications don't arrive even though an anomaly was detected</h4>
<ul>
<li>Check NetAlertX's own <strong>Notification Processing</strong> settings - the <code>Notify on</code> setting (<code>NTFPRCS_INCLUDED_SECTIONS</code>) must include <code>plugins</code>, or Watched/Report on matches never reach a notification (see the note above <code>Watched</code>/<code>Report on</code> in the settings table).</li>
<li>Confirm you actually have a publisher enabled and working under <strong>Settings → Notifications</strong> (ntfy, Apprise, email, ...) - this plugin never sends anything itself, so a working publisher there is a prerequisite, not optional.</li>
</ul>
<hr>
<h4 id="anomaly-label-missing-an-owner">❌ Anomaly label missing an owner</h4>
<ul>
<li>NetAlertX doesn't have <code>devOwner</code> set for that device yet, or the GraphQL lookup isn't reachable - neither blocks anomaly detection, the label is just less friendly.</li>
<li>Confirm <code>PIHOLEMON_GET_OWNER</code> is enabled, and that this app's own <strong>GRAPHQL_PORT</strong>/<strong>API_TOKEN</strong> settings (Settings → General) are correct, if you expect owners to resolve.</li>
</ul>
<hr>
<h4 id="getting-flagged-for-normal-usage-not-getting-flagged-for-a-real-spike">❌ Getting flagged for normal usage / not getting flagged for a real spike</h4>
<ul>
<li>Both <code>PIHOLEMON_MULTIPLIER</code> and <code>PIHOLEMON_MIN_BLOCKED</code> are starting values, not tuned defaults - let it run for a week and adjust based on what's actually normal for your network. They apply <em>per run</em>, so if you change <code>PIHOLEMON_RUN_SCHD</code> to something much less frequent than the default, <code>PIHOLEMON_MIN_BLOCKED</code> in particular may need raising (fewer, larger runs mean more blocked queries naturally accumulate in each one).</li>
<li><code>PIHOLEMON_HISTORY_DAYS</code> is a retention window, not a detection delay. A new device becomes evaluable after its 3rd successful run: the 1st anchors the raw counter, the 2nd records the first delta into the baseline history, and the 3rd is the first one with a baseline to compare against.</li>
<li>A device is also never flagged on the one run right after it's first seen, or right after Pi-hole/FTL restarts - see the delta note above the settings table.</li>
</ul>
<h3 id="notes">Notes</h3>
<ul>
<li>Device-import parsing (online/offline handling, fake-MAC fallback, endpoints used) mirrors the official <code>pihole_api_scan</code> plugin - this isn't meant to reinvent that half, only to support a second Pi-hole instance without forking it.</li>
<li>This plugin never blocks, unblocks, or otherwise changes anything on either Pi-hole - it only reads.</li>
<li>
<p>The rolling per-device history is kept in its own <code>state.PIHOLEMON.json</code> file in NetAlertX's DB folder (survives upgrades, unlike the log folder) - safe to delete if you want to reset the baseline from scratch. The per-run <code>last_result</code> file stays in this plugin's log directory as usual.</p>
</li>
<li>
<p>Version: 1.0.2</p>
</li>
<li>Author: <a href="https://github.com/mauricio-camayo/">mauricio-camayo</a></li>
<li>Release Date: <code>2026-08-31</code></li>
</ul>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"></path></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="Footer">
<a href="../pihole_api_scan/" class="md-footer__link md-footer__link--prev" aria-label="Previous: PiHole API scan (PIHOLEAPI)">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
Previous
</span>
<div class="md-ellipsis">
PiHole API scan (PIHOLEAPI)
</div>
</div>
</a>
<a href="../pihole_scan/" class="md-footer__link md-footer__link--next" aria-label="Next: PiHole (Device sync) (PIHOLE)">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
PiHole (Device sync) (PIHOLE)
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.footer", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.a7c05c9e.min.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(()=>{ lightbox.reload(); });
</script></body></html>