Skip to content

guycalledseven/technitium-dns-prometheus-exporter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Technitium DNS Prometheus Exporter

A lightweight Prometheus exporter for Technitium DNS Server (github) that exposes dashboard, DNS, zone, DHCP, and top‑query statistics for single servers or clusters. Includes an accompanying dashboard for visualization in Grafana.

Inspired by pihole-exporter and Pi-hole Exporter Grafana dashboard. After migrating from Pi-hole to Technitium, I couldn’t find any exporter that provided the metrics I needed while remaining simple and reliable — so I built one.

Design Notes

  • Cluster-Aware: Can monitor a complete Technitium cluster from a single exporter instance by proxying requests through the primary controller.
  • All metrics represent the current Technitium dashboard window, not cumulative counters.
  • No artificial counters or rate conversions
  • DNS traffic metrics reflect Technitium’s current dashboard statistics window (e.g. LastHour), not lifetime counters. Zone and DHCP metrics reflect current server state at scrape time.
  • Logging is explicit on API failures
  • Metric cardinality is intentionally bounded
  • Suitable for home labs and small/medium installations. Use of python over golang comes from the need for a quick and easy to understand solution without the need to define specific golang structs for each Technitium DNS API output, which could change any time and break strict golang exporter.

Configuration

All configuration is done via environment variables.

Variable Description Default
TECHNITIUM_BASE_URL Base URL of Technitium DNS API (the controller if using clustering) http://technitium:5380
TECHNITIUM_TOKEN Required API token (none)
TECHNITIUM_VERIFY_SSL SSL Verification (set to "false" if using self-signed certs) true
TECHNITIUM_STATS_RANGE Stats window (The duration type for which valid values are: LastHour, LastDay, LastWeek, LastMonth, LastYear, Custom. ) LastHour
TECHNITIUM_TOP_LIMIT Number of entries in Top lists (Clients/Domains). 50
EXPORTER_PORT Port exporter listens on 9105
LOG_LEVEL Logging level INFO
SERVER_LABEL Single Mode: Custom label for the server tag in Grafana. technitium
TECHNITIUM_NODES Cluster Mode: Comma-separated list of node names to scrape (optional). (unset)

Deployment Modes

The exporter supports two modes of Technitium DNS operation: single server and clustering.

Single Server Mode (default)

If TECHNITIUM_NODES is left empty, the server label in Prometheus/Grafana will be set to the value of SERVER_LABEL (default: technitium).

Clustering Mode

If you are running a Technitium cluster, you only need one exporter instance.

Point TECHNITIUM_BASE_URL to your primary controller. Set TECHNITIUM_NODES to a comma-separated list of the node names exactly as they appear in your Technitium panel.

Example: TECHNITIUM_NODES="primary-node,secondary-01,secondary-02"

The exporter will iterate through this list, asking the Controller to proxy requests to each node. Metrics will be tagged automatically: server="primary-node", server="secondary-01", etc.

Note: SERVER_LABEL is ignored in this mode.

Creating the Technitium DNS API token

The exporter needs a read-only API token to talk to Technitium DNS server.

Here’s only way I am aware of to generate one:

  • Open your Technitium instance in a browser.
  • Navigate to Administration > Groups and create a group named “read-only”.
  • Now create a user named “readonly” and make it a member of "read-only" group.
  • Go to Administration > Permissions and verify that Everyone has read-only access to everything.
  • Go to Zones > select zone > Permissions,
    • In Group Permissions > add group "read-only", Assign View permission to "read-only" group and click Save
    • Repeat for all Zones you wish to export
  • Log out of Technitium. Log back in as the readonly user you just created.
  • Click on readonly user's profile in the top-right corner and select “Create API token”.

Running with Docker Compose

With prebuild iamge

Available images are:

  • linux/amd64
  • linux/arm64
  • linux/arm/v7

Example docker-compose.yml for single Technitium instance :

  technitium_exporter:
    image: ghcr.io/guycalledseven/technitium-dns-prometheus-exporter:latest
    container_name: technitium_exporter
    depends_on:
      - prometheus
    restart: unless-stopped
    environment:
      TECHNITIUM_BASE_URL: http://technitium:5380
      # TECHNITIUM_BASE_URL: https://technitium::53443
      # TECHNITIUM_VERIFY_SSL: false
      TECHNITIUM_TOKEN: your-api-token-here
      SERVER_LABEL: technitium
      TECHNITIUM_STATS_RANGE: LastHour
      TECHNITIUM_TOP_LIMIT: 50
      EXPORTER_PORT: 9105
    ports:
      - "9105:9105"

Example for Technitium DNS cluster:

  technitium_exporter:
    image: ghcr.io/guycalledseven/technitium-dns-prometheus-exporter:latest
    container_name: technitium_exporter
    depends_on:
      - prometheus
    restart: unless-stopped
    environment:
      TECHNITIUM_BASE_URL: https://technitium:5380 # your controller
      TECHNITIUM_VERIFY_SSL: false # eg. has self signed cert
      TECHNITIUM_TOKEN: your-api-token-here
      TECHNITIUM_NODES: "primary-node,secondary-01,secondary-02" # your nodes
      TECHNITIUM_STATS_RANGE: LastHour
      TECHNITIUM_TOP_LIMIT: 50
      EXPORTER_PORT: 9105
    ports:
      - "9105:9105"

Prometheus scrape config:

scrape_configs:
  - job_name: technitium
    static_configs:
      - targets:
          - technitium-exporter:9105

Features

⚠️ Important: Due to how Technitium DNS currently exposes data - DNS traffic metrics are window-based snapshots, not lifetime counters.
They reflect Technitium’s current dashboard statistics window (TECHNITIUM_STATS_RANGE — e.g., LastHour, LastDay, LastWeek).
Values may increase or decrease over time as the window slides.

Window-based DNS Traffic Metrics

These metrics come from /api/dashboard/stats/get and /api/dashboard/stats/getTop and represent “stats over the last X”:

  • technitium_dns_queries_window{server, category}
  • technitium_dns_response_type_total{server, type}
  • technitium_dns_query_type_total{server, qtype}
  • technitium_dns_protocol_queries{server, protocol}
  • technitium_dns_top_domain_hits{server, domain}
  • technitium_dns_top_blocked_domain_hits{server, domain}
  • technitium_dns_top_client_hits{server, client_ip, client_name}
  • technitium_dns_clients_window{server}

Use these for:

  • % blocked
  • Cache hit ratio
  • Query mix breakdown
  • Error & NXDOMAIN analysis
  • Top talkers and Pi-hole-style dashboards

Snapshot-of-State Metrics (Inventory / Configuration)

These reflect the current state of the DNS server, unaffected by the stats window:

  • technitium_dns_zones{server}
  • technitium_dns_cached_entries{server}
  • technitium_dns_allowed_zones{server}
  • technitium_dns_blocked_zones{server}
  • technitium_dns_allowlist_zones{server}
  • technitium_dns_blocklist_zones{server}
  • technitium_zone_info{server, zone, type, disabled, internal, serial}
  • technitium_dhcp_leases_total{server, scope, type}

Use these for:

  • Zone inventory and health
  • Blocklist/allowlist statistics
  • Cache size monitoring
  • DHCP scope usage

Exporter & Health Metrics

Exporter + API health:

  • technitium_up{server} — API reachability (0/1)
  • technitium_scrape_duration_seconds{server} — exporter scrape duration

Python client process metrics:

  • python_gc_*
  • python_info

Metrics Overview

Core Health

  • technitium_up{server}
  • technitium_scrape_duration_seconds{server}

DNS Queries (Window Snapshot)

  • technitium_dns_queries_window{server, category}

Categories:

all
no_error
nxdomain
servfail
refused
authoritative
recursive
cached
blocked
dropped

Breakdown Metrics

  • technitium_dns_response_type_total{server, type}
  • technitium_dns_query_type_total{server, qtype}
  • technitium_dns_protocol_queries{server, protocol}

Top Lists

  • technitium_dns_top_client_hits{server, client_ip, client_name}
  • technitium_dns_top_domain_hits{server, domain}
  • technitium_dns_top_blocked_domain_hits{server, domain}

Zones

  • technitium_zone_info{server, zone, type, disabled, internal, serial}
  • technitium_dns_zones{server}
  • technitium_dns_allowed_zones{server}
  • technitium_dns_blocked_zones{server}
  • technitium_dns_allowlist_zones{server}
  • technitium_dns_blocklist_zones{server}
  • technitium_dns_cached_entries{server}

DHCP

  • technitium_dhcp_leases_total{server, scope, type}

Roadmap

  • Per‑client block rate

  • Per‑zone query statistics

  • DNSSEC / DoH / DoT breakdowns

  • Rate‑limited client metrics

  • Optional caching layer to reduce API calls?

  • Experiment with custom length window with Custom type which takes start/end into consideration:

                    if (type == DashboardStatsType.Custom)
                    {
                        string strStartDate = request.GetQueryOrForm("start");
                        string strEndDate = request.GetQueryOrForm("end");
    

Accompanying Grafana dashboard

Available in repo and Grafana dashboards.

Technitium DNS Grafana dashboard

License

Apache License 2.0


About

A lightweight Prometheus exporter for Technitium DNS Server that exposes dashboard, DNS, zone, DHCP, and top‑query statistics for single servers or clusters with accompanying dashboard for visualization in Grafana.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors