Skip to content

dnsweaver

Automatic DNS management for Docker, Kubernetes, and Proxmox VE workloads with multi-provider support.

dnsweaver watches Docker events, Kubernetes resources, and Proxmox VE clusters to automatically create and delete DNS records. Unlike single-provider or single-platform tools, dnsweaver supports split-horizon DNS, multiple DNS providers simultaneously, and works across Docker, Docker Swarm, Kubernetes, and Proxmox VE — or all of them at once.


Key Features

  • Multi-Provider Support


    Route different domains to different DNS providers. Seven providers: Technitium, Cloudflare, AdGuard Home, RFC 2136, Pi-hole, dnsmasq, and webhook.

    Providers

  • Split-Horizon DNS


    Create internal and external records from the same container labels automatically. One label, multiple zones.

    Split-Horizon Guide

  • Docker, Swarm & Kubernetes


    First-class support for Docker, Docker Swarm, and Kubernetes. Run on one platform or all three simultaneously.

    Sources Overview

  • Proxmox VE


    Auto-creates A records for VMs and LXC containers by polling the PVE API. Filter by node, tag, or VM state.

    Proxmox Source

  • Observable


    Prometheus metrics, health endpoints, and structured logging built-in. Know what's happening.

    Observability

How It Works

flowchart LR
    A["Docker / Swarm"] --> B["dnsweaver"]
    D["Kubernetes"] --> B
    P["Proxmox VE"] --> B
    B --> C["DNS Providers<br/>(create / update / delete)"]
  1. A container starts with a Traefik label:

    labels:
      - "traefik.http.routers.myapp.rule=Host(`myapp.home.example.com`)" # (1)!
    
    1. dnsweaver extracts hostnames from Traefik router labels and native dnsweaver.* labels
  2. dnsweaver extracts the hostname and matches it against configured provider domain patterns

  3. The matching provider creates the DNS record:

    • A record: myapp.home.example.com → 192.0.2.100
    • CNAME: myapp.example.com → proxy.example.com
  4. When the container stops, the DNS record is automatically cleaned up

  1. An Ingress, IngressRoute, HTTPRoute, or annotated Service is created:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: myapp
    spec:
      rules:
        - host: myapp.home.example.com # (1)!
    
    1. dnsweaver watches Ingress, IngressRoute (Traefik CRD), HTTPRoute (Gateway API), and Service resources
  2. dnsweaver extracts the hostname and matches it against configured provider domain patterns

  3. The matching provider creates the DNS record:

    • A record: myapp.home.example.com → 192.0.2.100
    • CNAME: myapp.example.com → proxy.example.com
  4. When the resource is deleted, the DNS record is automatically cleaned up

  1. A VM or LXC container is running with a QEMU guest agent (or LXC network configured):

    # VM example: qm set 100 --name myvm --tags web # (1)!
    
    1. dnsweaver polls the PVE API and discovers VMs via QEMU guest agent IPs or LXC container IPs from net0 config
  2. dnsweaver extracts the VM or LXC hostname and IP, then matches against configured provider domain patterns

  3. The matching provider creates the DNS record:

    • A record: myvm.home.example.com → 192.0.2.10
  4. When the VM or LXC is stopped or deleted, the DNS record is automatically cleaned up

Quick Start

services:
  dnsweaver:
    image: maxamill/dnsweaver:latest
    environment:
      - DNSWEAVER_INSTANCES=internal-dns # (1)!
      - DNSWEAVER_INTERNAL_DNS_TYPE=technitium # (2)!
      - DNSWEAVER_INTERNAL_DNS_URL=http://dns.internal:5380
      - DNSWEAVER_INTERNAL_DNS_TOKEN_FILE=/run/secrets/technitium_token
      - DNSWEAVER_INTERNAL_DNS_ZONE=home.example.com
      - DNSWEAVER_INTERNAL_DNS_RECORD_TYPE=A
      - DNSWEAVER_INTERNAL_DNS_TARGET=192.0.2.100 # (3)!
      - DNSWEAVER_INTERNAL_DNS_DOMAINS=*.home.example.com # (4)!
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    secrets:
      - technitium_token
  1. Comma-separated list of provider instance names
  2. Provider type: technitium, cloudflare, pihole, adguard, dnsmasq, rfc2136, or webhook
  3. Target IP for A records (or CNAME target hostname)
  4. Domain patterns to match—wildcards supported
helm install dnsweaver oci://ghcr.io/maxfield-allison/charts/dnsweaver \
  --namespace dnsweaver --create-namespace \
  --set config.instances="internal-dns" \
  --set config.providers.internal-dns.type=technitium \
  --set config.providers.internal-dns.url=http://dns.internal:5380 \
  --set config.providers.internal-dns.zone=home.example.com \
  --set config.providers.internal-dns.recordType=A \
  --set config.providers.internal-dns.target=192.0.2.100 \
  --set config.providers.internal-dns.domains="*.home.example.com"
kubectl apply -k https://github.com/maxfield-allison/dnsweaver/deploy/kustomize/base

Then configure via ConfigMap and Secret. See the Kubernetes deployment guide.

Getting Started Configuration

Supported Providers

Provider Record Types Notes
Technitium A, AAAA, CNAME, SRV, TXT Full-featured self-hosted DNS
Cloudflare A, AAAA, CNAME, SRV, TXT With optional proxy support
RFC 2136 A, AAAA, CNAME, SRV, TXT BIND, Windows DNS, PowerDNS, Knot
Pi-hole A, CNAME API or file mode
AdGuard Home A, AAAA, CNAME DNS rewrite management
dnsmasq A, CNAME File-based configuration
Webhook A, AAAA, CNAME, TXT Custom integrations

Why dnsweaver?

dnsweaver external-dns docker-dns-gen
Docker support
Kubernetes support
Proxmox VE support
Multiple providers
Split-horizon DNS
Self-hosted DNS focus
No CRDs required N/A

Next Steps

  • Getting Started


    Install and configure dnsweaver in minutes — Docker or Kubernetes.

    Quick Start Guide

  • Configuration


    Environment variables, YAML config, and secrets reference.

    Configuration Docs

  • Deployment Guides


    Production-ready configs for Docker Compose, Swarm, and Kubernetes.

    Deployment

  • Split-Horizon DNS


    Internal + external records from one config.

    Split-Horizon Guide