Automatic DNS record 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 tools, dnsweaver supports split-horizon DNS, multiple DNS providers simultaneously, and works across Docker, Kubernetes, and Proxmox platforms.
π Full Documentation
- π Multi-Provider Support β Route different domains to different DNS providers
- π Split-Horizon DNS β Internal and external records from the same container labels
- π³ Docker & Swarm β Works with standalone Docker and Docker Swarm clusters
- βΈοΈ Kubernetes Native β Watches Ingress, IngressRoute, HTTPRoute, and Service resources via Helm or Kustomize
- π₯οΈ Proxmox VE β Auto-creates A records for VMs (via QEMU guest agent) and LXC containers
- ποΈ Multi-Instance Safe β Run multiple dnsweaver instances on the same DNS zone without conflicts
- π Socket Proxy Compatible β Connect via TCP to a Docker socket proxy for improved security
- π‘οΈ Hardened TLS β Unified per-instance TLS controls (custom CA, mTLS client certs, SNI override, configurable min version; TLS 1.2 floor by default) for every HTTP-based provider and the Proxmox source
- π·οΈ Traefik Integration β Parses
traefik.http.routers.*.rulelabels to extract hostnames - π Caddy Integration β Parses
caddy/caddy_<n>labels from caddy-docker-proxy - π§ nginx-proxy Integration β Parses
VIRTUAL_HOSTlabels used by jwilder/nginx-proxy - π Observable β Prometheus metrics, health endpoints, structured logging
- π Secrets Support β Docker secrets and Kubernetes Secrets via
_FILEsuffix variables
| 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 | Any | Custom integrations |
# Docker Hub
docker pull maxamill/dnsweaver:latest
# GitHub Container Registry
docker pull ghcr.io/maxfield-allison/dnsweaver:latestservices:
dnsweaver:
image: maxamill/dnsweaver:latest
restart: unless-stopped
environment:
- DNSWEAVER_INSTANCES=internal-dns
- DNSWEAVER_INTERNAL_DNS_TYPE=technitium
- 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
- DNSWEAVER_INTERNAL_DNS_DOMAINS=*.home.example.com
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
secrets:
- technitium_token
secrets:
technitium_token:
external: trueflowchart LR
A["Docker / Swarm"] --> B["dnsweaver"]
D["Kubernetes"] --> B
P["Proxmox VE"] --> B
B --> C["DNS Providers<br/>(create / update / delete)"]
-
A container starts with a Traefik label (or a Kubernetes Ingress/HTTPRoute is created):
labels: - "traefik.http.routers.myapp.rule=Host(`myapp.home.example.com`)"
-
dnsweaver extracts the hostname and matches it against configured provider domain patterns
-
The matching provider creates the DNS record:
- A record:
myapp.home.example.com β 192.0.2.100 - CNAME:
myapp.example.com β proxy.example.com
- A record:
-
When the container stops (or the Kubernetes resource is deleted), the DNS record is automatically cleaned up
| Topic | Description |
|---|---|
| Getting Started | Installation and first configuration |
| Configuration | Environment variables reference |
| Providers | Provider-specific setup guides |
| Sources | Docker, Kubernetes, Proxmox, Traefik file sources |
| Kubernetes | Kubernetes deployment with Helm/Kustomize |
| Proxmox VE | Auto-DNS for VMs and LXC containers |
| Split-Horizon DNS | Internal + external records |
| Docker Swarm | Swarm deployment guide |
| Observability | Metrics, logging, and health checks |
| FAQ | Common questions and troubleshooting |
Every HTTP-based provider (Technitium, AdGuard Home, Cloudflare, Pi-hole, Webhook) and the Proxmox source share a single TLS configuration surface:
| Env key (per instance) | Purpose |
|---|---|
DNSWEAVER_<NAME>_TLS_CA_FILE |
Trust a private CA bundle (PEM) |
DNSWEAVER_<NAME>_TLS_CERT_FILE / _TLS_KEY_FILE |
Present a client certificate (mTLS) |
DNSWEAVER_<NAME>_TLS_SERVER_NAME |
Override SNI / hostname verification |
DNSWEAVER_<NAME>_TLS_SKIP_VERIFY |
Disable verification (development only) |
DNSWEAVER_<NAME>_TLS_MIN_VERSION |
1.2 (default) or 1.3 |
The Proxmox source uses the same keys under DNSWEAVER_PROXMOX_TLS_*. The legacy *_INSECURE_SKIP_VERIFY and DNSWEAVER_PROXMOX_VERIFY_TLS variables are still accepted but emit a deprecation warning at startup β migrate to the unified TLS_SKIP_VERIFY keys. See the Environment Reference and SECURITY.md for full details and recipes.
Deploy dnsweaver to watch Kubernetes resources for DNS management:
# Using Kustomize
kubectl apply -k https://github.com/maxfield-allison/dnsweaver/deploy/kustomize/base
# Using Helm
helm install dnsweaver deploy/helm/dnsweaver/ \
--namespace dnsweaver --create-namespacednsweaver automatically detects hostnames from Ingress, IngressRoute (Traefik), HTTPRoute (Gateway API), and Service resources. Use dnsweaver.dev/* annotations for per-resource overrides:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
dnsweaver.dev/record-type: "A"
dnsweaver.dev/target: "192.0.2.100"
spec:
rules:
- host: app.example.comSee the Kubernetes deployment guide for full configuration.
Manage internal and external DNS from the same container labels:
environment:
- DNSWEAVER_INSTANCES=internal,external
# Internal: Technitium β private IP
- DNSWEAVER_INTERNAL_TYPE=technitium
- DNSWEAVER_INTERNAL_RECORD_TYPE=A
- DNSWEAVER_INTERNAL_TARGET=192.0.2.100
- DNSWEAVER_INTERNAL_DOMAINS=*.example.com
# External: Cloudflare β tunnel CNAME
- DNSWEAVER_EXTERNAL_TYPE=cloudflare
- DNSWEAVER_EXTERNAL_RECORD_TYPE=CNAME
- DNSWEAVER_EXTERNAL_TARGET=tunnel.example.com
- DNSWEAVER_EXTERNAL_DOMAINS=*.example.comWith this configuration, when app.example.com starts:
- Internal DNS β
Arecord β192.0.2.100 - External DNS β
CNAMErecord βtunnel.example.com
Contributions are welcome! See CONTRIBUTING for guidelines.