Native dnsweaver Labels¶
While dnsweaver primarily extracts hostnames from Traefik labels, you can also use native dnsweaver labels for services that don't use Traefik.
Why Use Native Labels?¶
- Services without a reverse proxy
- Direct DNS records for non-HTTP services
- More explicit control over DNS records
- Services using a different reverse proxy (Nginx, Caddy, etc.)
Enabling Native Labels¶
Add dnsweaver to the sources:
Or use only native labels:
Label Format¶
Basic Hostname¶
Multiple Hostnames (Comma-Separated)¶
For multiple hostnames without the verbosity of named records:
Whitespace around commas is trimmed and empty values are skipped. This can be combined with dnsweaver.ttl, dnsweaver.proxied, and dnsweaver.adopt, which apply to all hostnames in the list.
Both dnsweaver.hostname (singular) and dnsweaver.hostnames (plural) can be used together — all hostnames are processed.
Multiple Hostnames (Named Records)¶
For multiple hostnames with per-record options, use the named records format:
labels:
- "dnsweaver.records.primary.hostname=app1.example.com"
- "dnsweaver.records.secondary.hostname=app2.example.com"
With Options¶
labels:
- "dnsweaver.hostname=myapp.example.com"
- "dnsweaver.ttl=600" # Override default TTL
- "dnsweaver.enabled=true" # Explicit enable (default)
Disable for Specific Container¶
Label Reference¶
Simple Labels¶
| Label | Default | Description |
|---|---|---|
dnsweaver.hostname |
- | Single hostname to create |
dnsweaver.hostnames |
- | Comma-separated list of hostnames |
dnsweaver.instances |
all matching providers | Comma-separated provider instance names for all hostnames on the workload, including other sources. See workload selection. |
dnsweaver.enabled |
true |
Enable/disable processing |
dnsweaver.ttl |
- | Override TTL for this container |
dnsweaver.proxied |
provider default | Cloudflare proxy (orange-cloud) override — true or false. Applies to every hostname on the container. Ignored by non-Cloudflare providers. |
dnsweaver.adopt |
provider/global policy | Enable or disable existing-record adoption for every hostname discovered from this workload, including hostnames found by Traefik. Enabling requires the matching provider's ADOPT_EXISTING_ALLOW_OVERRIDES gate. Disabling is always honored. |
Named Record Labels¶
For advanced use cases, use the named record format: dnsweaver.records.<name>.<field>
| Label Pattern | Default | Description |
|---|---|---|
dnsweaver.records.<name>.hostname |
- | Hostname for this record (required) |
dnsweaver.records.<name>.type |
A |
Record type: A, AAAA, CNAME, SRV, TXT |
dnsweaver.records.<name>.target |
- | Override target (IP or hostname) |
dnsweaver.records.<name>.provider |
- | Override the workload selection for this record; the instance must still match the configured domain and workload filters |
dnsweaver.records.<name>.ttl |
- | TTL for this specific record |
dnsweaver.records.<name>.port |
- | Port (for SRV records) |
dnsweaver.records.<name>.priority |
- | Priority (for SRV records) |
dnsweaver.records.<name>.weight |
- | Weight (for SRV records) |
dnsweaver.records.<name>.enabled |
true |
Enable/disable this record |
dnsweaver.records.<name>.proxied |
provider default | Cloudflare proxy (orange-cloud) override for this record — true or false. Ignored by non-Cloudflare providers. |
dnsweaver.records.<name>.adopt |
workload/provider/global policy | Override existing-record adoption for this named record. Enabling requires the matching provider's ADOPT_EXISTING_ALLOW_OVERRIDES gate. Disabling is always honored. |
dnsweaver.records.<name>.meta.<key> |
- | Arbitrary provider metadata passed through to the target provider (advanced). |
An explicit provider hint narrows routing; it does not bypass that provider's domain patterns, exclusions or workload-metadata filters. If an existing named record stops matching after an upgrade, correct the operator's provider scope rather than granting access through a workload label.
Existing-record adoption¶
services:
app:
labels:
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "dnsweaver.adopt=true"
The workload label applies even when Traefik, rather than the native source, discovers the hostname. The matching provider must explicitly allow the request:
Use a named record to narrow or override the workload setting:
labels:
- "dnsweaver.adopt=true"
- "dnsweaver.records.manual.hostname=manual.example.com"
- "dnsweaver.records.manual.adopt=false"
Examples¶
Database Server¶
Create A record for a database:
Multi-Hostname Service¶
Create records for each service endpoint using named records:
services:
minio:
image: minio/minio
labels:
- "dnsweaver.records.console.hostname=minio.example.com"
- "dnsweaver.records.api.hostname=s3.example.com"
SRV Record (Minecraft Server)¶
Create an SRV record for service discovery:
services:
minecraft:
image: itzg/minecraft-server
labels:
- "dnsweaver.records.mc.hostname=_minecraft._tcp.mc.example.com"
- "dnsweaver.records.mc.type=SRV"
- "dnsweaver.records.mc.port=25565"
- "dnsweaver.records.mc.priority=10"
- "dnsweaver.records.mc.weight=100"
Cloudflare Proxy Override (Per-Host)¶
When a hostname is served by a Cloudflare provider,
the proxied label overrides that provider's PROXIED default on a per-host
basis. This is the typical "most services proxied, a few DNS-only" pattern —
keep the provider default proxied and flip individual hosts off.
Simple hostname form (applies to every hostname on the container):
labels:
- "dnsweaver.hostname=ssh.example.com"
- "dnsweaver.proxied=false" # DNS-only, bypass Cloudflare's proxy
Named-record form (mix proxied and DNS-only on one service):
labels:
- "dnsweaver.records.app.hostname=app.example.com"
- "dnsweaver.records.app.proxied=true" # orange-cloud
- "dnsweaver.records.ssh.hostname=ssh.example.com"
- "dnsweaver.records.ssh.proxied=false" # DNS-only
- "dnsweaver.records.vpn.hostname=vpn.example.com"
- "dnsweaver.records.vpn.proxied=false" # DNS-only
When a record does not set proxied, the Cloudflare instance's
DNSWEAVER_{NAME}_PROXIED value (default true) is used as the fallback. The
label is ignored by providers that have no concept of proxying.
Adding, changing or removing the label updates a record that already exists:
on the next reconciliation dnsweaver compares the record's proxied state with
what the label (or the instance default) now asks for and updates it in place
when they differ. The same applies when DNSWEAVER_{NAME}_PROXIED itself is
changed.
Combine with Traefik Labels¶
Use both Traefik and native labels:
services:
webapp:
image: myapp:latest
labels:
# Traefik for HTTP routing
- "traefik.http.routers.webapp.rule=Host(`webapp.example.com`)"
# Additional DNS record via dnsweaver
- "dnsweaver.hostname=webapp-direct.example.com"
Both hostnames will be processed (if both sources are enabled).
Docker Compose Example¶
services:
dnsweaver:
image: maxamill/dnsweaver:latest
environment:
- DNSWEAVER_SOURCES=dnsweaver # Only native labels
- DNSWEAVER_INSTANCES=internal
- DNSWEAVER_INTERNAL_TYPE=technitium
- DNSWEAVER_INTERNAL_URL=http://dns:5380
- DNSWEAVER_INTERNAL_TOKEN_FILE=/run/secrets/dns_token
- DNSWEAVER_INTERNAL_ZONE=example.com
- DNSWEAVER_INTERNAL_RECORD_TYPE=A
- DNSWEAVER_INTERNAL_TARGET=192.0.2.100
- DNSWEAVER_INTERNAL_DOMAINS=*.example.com
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
my-service:
image: nginx
labels:
- "dnsweaver.hostname=my-service.example.com"
Priority and Conflicts¶
When a container has both Traefik and dnsweaver labels:
- Both sources are processed independently
- Duplicate hostnames are deduplicated
- No conflict - same hostname from multiple sources creates one record
Swarm Mode¶
For Swarm, labels go on the service (same as Traefik):