The implementation of a robust DNS filtering solution like AdGuard Home necessitates more than just the deployment of a blocking engine; it requires a comprehensive observability stack to ensure the health, performance, and security of the network perimeter. When managing DNS at scale, the ability to visualize query patterns, identify top-offending clients, and monitor upstream latency is critical for maintaining network integrity. By integrating AdGuard Home with the Prometheus ecosystem and utilizing specialized Grafana dashboards, network administrators can transform raw DNS logs into actionable intelligence. This architecture relies on the synergy between the AdGuard Home API, specialized exporters—such as the AdGuard Home Exporter and the ebrianne/adguard-exporter—and the Prometheus time-series database to create a high-fidelity monitoring environment. This technical deep dive explores the configuration of these components, the metrics available for ingestion, and the deployment strategies required to maintain a production-grade monitoring pipeline.
The Architecture of DNS Observability
A professional monitoring stack for AdGuard Home functions through a multi-layered telemetry pipeline. At the foundation lies the AdGuard Home instance itself, which acts as the primary data producer. This instance exposes various endpoints through its internal API, including /control/stats, /control/querylog, and /control/status. However, raw API endpoints are not natively compatible with the pull-based architecture of Prometheus. Therefore, an intermediary layer, known as an exporter, is required to scrape these API endpoints, translate the JSON responses into Prometheus-compatible metric formats, and host them on a dedicated HTTP port.
The exporter acts as a translator, converting complex web responses into numerical time-scale data. For instance, when the exporter queries the /control/stats endpoint, it captures the current count of blocked queries and processes them into a format that Prometheus can scrape. This translation layer is vital because it allows for the calculation of rates, such as the increase in blocked domains over a specific time interval, which is essential for detecting sudden spikes in malware-related DNS activity. Once the Prometheus server scrapes these metrics, they are stored in a time-series database, allowing Grafana to query historical data to produce trends, heatmaps, and alerts.
The complexity of this architecture increases when managing multi-instance environments. In large-scale deployments, a single exporter can be configured to monitor multiple AdGuard Home servers simultaneously. This is achieved by providing comma-separated lists of targets, usernames, and passwords to the exporter's configuration. This capability ensures that a single Grafana dashboard can provide a unified view of the entire DNS infrastructure, rather than forcing administrators to switch between disconnected monitoring silos.
Technical Specifications of Prometheus Exporters
The ecosystem contains several distinct exporters, each offering different levels of granularity and feature sets. Choosing the correct exporter depends heavily on the specific monitoring requirements, such as whether the focus is on simple uptime or deep-packet inspection of query types.
AdGuard Home Multi-Instance Exporter Capabilities
The JonanekDev/AdGuardHome-Exporter is specifically engineered for environments where high availability and multi-server redundancy are required. It excels at aggregating data from disparate AdGuard instances into a single cohesive dataset.
| Feature Category | Detailed Capability | Impact on Network Administration |
|---|---|---|
| Multi-Instance Support | Simultaneous monitoring of multiple AdGuard servers | Enables unified visibility across distributed network segments |
| DNS Query Analytics | Tracking of total queries and blocked counts | Provides immediate insight into the volume of network traffic |
| Client Activity Tracking | Granular monitoring of per-client query statistics | Allows for the identification of specific devices causing high traffic |
| Upstream Performance | Monitoring of upstream DNS latency and health | Facilitates proactive troubleshooting of external DNS resolution issues |
| Filter Usage Metrics | Visibility into the effectiveness of blocklists | Helps administrators optimize filter lists to reduce false positives |
| Instance Health | Real-time monitoring of server availability | Ensures rapid response to service outages or crashes |
ebrianne/adguard-exporter Metric Granularity
The ebrianne/adguard-exporter, often used in Raspberry Pi and lightweight Docker deployments, focuses on specific DNS-centric metrics that are essential for understanding the "why" behind blocked traffic.
| Metric Name | Technical Description | Operational Significance |
|---|---|---|
| adguardavgprocessing_time | Average time taken to process a DNS query | Identifies latency bottlenecks in the DNS resolution pipeline |
| adguardnumblocked_filtering | Total number of queries blocked by filters | Measures the overall effectiveness of the security layer |
| adguardnumdns_queries | Total count of all DNS queries processed | Servates as a baseline for total network DNS load |
| adguardnumreplaced_parental | Queries blocked specifically due to parental controls | Monitors the enforcement of content filtering policies |
| adguardnumreplaced_safebrowsing | Queries blocked via Safe Browsing lists | Tracks protection against known phishing and malware sites |
| argadnumreplaced_safesearch | Queries blocked via SafeSearch enforcement | Confirms the active filtering of explicit content |
| adguardtopblocked_domains | List of the most frequently blocked domains | Reveals common threats or tracking attempts in the network |
| adguardtopclients | List of the most active DNS clients | Pinpoints devices with aggressive or malicious behavior |
| adguardtopqueried_domains | List of the most requested domains | Assists in capacity planning and traffic analysis |
| adguardquerytypes | Breakdown of DNS record types (A, AAAA, CNAME, etc.) | Useful for identifying non-standard or suspicious traffic patterns |
| running | Boolean status of the AdGuard service | The primary metric for heartbeat and uptime monitoring |
| protection_enabled | Boolean status of the filtering engine | Critical alert metric to ensure the security layer hasn't been disabled |
Advanced Telemetry and GeoIP Enrichment
Modern observability goes beyond simple counting; it involves enriching raw data with geographic and organizational context. Advanced exporters implement GeoIP enrichment using the MaxMind GeoLite2 database. This allows the Grafana dashboard to move from a list of IP addresses to a visual representation of the world.
The enrichment process follows a specific workflow:
1. The exporter retrieves the client IP from the AdGuard query log.
2. The exporter performs a lookup against a local GeoIP cache.
3. The resulting country or city information is attached to the metric.
4. Grafana uses the Geomap plugin to plot these points on a global map.
This capability enables the creation of a "DNS Threat Map," where administrators can see real-lag attacks originating from specific geographic regions. Furthermore, the ability to group DNS queries by ISP or organization allows for sophisticated traffic analytics, such as identifying if a specific service provider is causing increased latency through DNS hijacking or misconfiguration. To ensure this does not degrade performance, exporters implement a GeoIP caching mechanism and a deduplication cache, which prevents the inflation of metrics by ensuring that identical queries are processed only once within a specific window.
Deployment Orchestration and Configuration
Deploying these exporters requires precise configuration of environment variables and container orchestration. The method of deployment varies based on whether the environment uses standalone Docker, Docker Compose, or Kubernetes.
Docker and Docker Compose Implementation
For single-container deployments, the ebrian or ebrianne/adguard-exporter can be initialized via a standard docker run command. It is imperative to map the configuration via environment variables to ensure the exporter knows which AdGuard instance to target.
Example of a single-container deployment:
docker
docker run \
-e 'adguard_protocol=http' \
-e 'adguard_hostname=192.168.10.252' \
-e 'adguard_username=admin' \
-e 'adguard_password=mypassword' \
-e 'interval=10s' \
-e 'log_limit=10000' \
-e 'server_port=9617' \
-p 9617:9617 \
ebrianne/adguard_exporter:latest
In more complex environments, using an .env file is recommended to maintain security and prevent sensitive credentials from appearing in the process list. For high-security production environments, Docker Secrets can be utilized to inject passwords into the container without exposing them in the configuration files.
Example of a Docker Compose configuration using secrets:
```yaml
version: "3.7"
services:
adguardexporter:
image: ebrianne/adguardexporter:latest
restart: always
secrets:
- my-adguard-pass
ports:
- "9617:9617"
environment:
- adguardprotocol=http
- adguardhostname=192.168.10.252
- adguardusername=admin
- adguardpassword=/run/secrets/my-adguard-pass
- interval=10s
- log_limit=10000
secrets:
my-adguard-pass:
external: true
```
To create the required secret in a Docker Swarm environment, the following command is used:
bash
echo "mypassword" | docker secret create my-guard-pass -
Kubernetes and Prometheus ServiceMonitor Configuration
In a Kubernetes ecosystem, the deployment must be integrated with the Prometheus Operator. This requires a two-step configuration: defining a Service that exposes the metrics port and a ServiceMonitor that instructs Prometheus to scrape that service.
The Service definition must include both the standard HTTP port (80) and the metrics port (e.g., 8000).
Example service.yaml:
yaml
apiVersion: v1
kind: Service
metadata:
name: adguard-http
namespace: adguard
labels:
app: adguard
spec:
selector:
app: adguard
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
- port: 8000
protocol: TCP
targetPort: 8000
name: metrics
type: ClusterIP
The ServiceMonitor is the critical component that links the Service to the Prometheus scraping loop. It must be configured with the correct namespace selector and scrape interval.
Example servicemonitor.yaml:
yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: adguard-metrics
namespace: adguard
labels:
app: adguard
spec:
selector:
matchLabels:
app: adguard
namespaceSelector:
matchNames:
- adguard
endpoints:
- port: metrics
interval: 30s
path: /metrics
The deployment of the exporter itself within Kubernetes should follow security best practices, such as running as a non-root user and dropping unnecessary Linux capabilities.
Example of a hardened exporter deployment fragment:
yaml
containers:
- name: adguard-exporter
image: ghcr.io/sholdee/adguard-exporter:v2.0.2
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
ports:
- containerPort: 8000
name: metrics
protocol: TCP
livenessProbe:
httpGet:
path: /livez
port: metrics
readinessProbe:
httpGet:
path: /readyz
port: metrics
Prometheus Scrape Configuration
Once the exporter is running and accessible, Prometheus must be configured to ingest the data. This is done by modifying the prometheus.yml configuration file to include a new job specifically for AdGuard Home.
The scrape_configs section must be updated with the following structure:
yaml
scrape_configs:
- job_name: "adguardhome"
static_configs:
- targets: ["127.0.0.1:9100"]
In this configuration, the targets list should point to the IP address and port where the exporter is listening. If using a multi-instance exporter, the exporter itself handles the internal logic of querying the various AdGuard Home servers, so Prometheus only needs to point to the single exporter endpoint.
Analysis of Advanced Metrics and DHCP Monitoring
Beyond simple DNS query tracking, advanced monitoring configurations allow for the inspection of DHCP-related metrics. This is particularly useful in environments where AdGuard Home is also acting as the DHCP server for the network.
The following metrics provide insight into the state of the network's IP assignment:
- adguard_dhcp_enabled: A boolean metric indicating whether the DHCP server functionality is active.
- adguard_dhcp_leases: A metric representing the current number of active DHCP leases.
Monitoring these metrics allows administrators to detect "lease exhaustion," a condition where the DHCP pool is full and new devices cannot join the network. Furthermore, tracking the adguard_top_upstreams_avg_response_time_seconds allows for the identification of specific upstream DNS providers (like Cloudflare, Google, or Quad9) that may be experiencing regional latency, enabling automated failover or manual reconfiguration of the DNS upstream settings.
Conclusion
The integration of AdGuard Home with Grafana and Prometheus represents the pinnacle of network DNS observability. By moving beyond the basic web interface and implementing a structured telemetry pipeline, administrators gain the ability to perform deep forensic analysis on network traffic. The use of specialized exporters enables a transition from reactive troubleshooting—responding to outages after they occur—to proactive management, where latency trends, client behavior anomalies, and upstream performance degradation are identified before they impact end-users. Whether deploying a single Raspberry Pi instance or a global multi-instance cluster via Kubernetes, the architectural principles of metric collection, enrichment, and visualization remain the same. The deployment of high-fidelity dashboards, enriched with GeoIP data and detailed DNS statistics, transforms the DNS layer from a black box into a transparent, highly manageable component of the modern software-defined network.