external-dns-tidydns-webhook

April 17, 2026 · View on GitHub

A webhook provider for ExternalDNS that manages DNS records in TidyDNS.

Features

  • Supports A, CNAME, TXT, and SRV record types
  • Zone caching with configurable background refresh interval
  • Domain filtering (plain suffix, exclusion lists, and regex patterns)
  • OpenTelemetry traces and metrics (Prometheus /metrics endpoint)

Deployment

The webhook runs as a sidecar alongside ExternalDNS. Deploy it using the external-dns Helm chart:

# values.yaml
policy: sync

provider:
  name: webhook
  webhook:
    image:
      repository: ghcr.io/neticdk/external-dns-tidydns-webhook
      tag: latest  # pin to a release tag in production
    env:
      - name: TIDYDNS_USER
        valueFrom:
          secretKeyRef:
            name: tidydns-credentials
            key: username
      - name: TIDYDNS_PASS
        valueFrom:
          secretKeyRef:
            name: tidydns-credentials
            key: password
    args:
      - --tidydns-endpoint=https://tidy.example.com/index.cgi
      - --domain-filter=example.com
helm install external-dns external-dns/external-dns -f values.yaml

Note

Create the Kubernetes Secret before deploying:

kubectl create secret generic tidydns-credentials \
  --from-literal=username='<tidydns-user>' \
  --from-literal=password='<tidydns-password>'

Endpoints

PortPathDescription
8888/Webhook API (consumed by ExternalDNS sidecar, bound to 127.0.0.1)
8080/healthzHealth check
8080/metricsPrometheus metrics

Configuration

All flags can also be set via environment variables (uppercase, underscores instead of dashes, e.g. TIDYDNS_ENDPOINT).

FlagEnvDefaultDescription
--tidydns-endpointTIDYDNS_ENDPOINT(required)TidyDNS server URL
TIDYDNS_USERTidyDNS username
TIDYDNS_PASSTidyDNS password
--zone-update-intervalZONE_UPDATE_INTERVAL10mInterval for background zone refresh
--max-concurrencyMAX_CONCURRENCY10Max concurrent TidyDNS API calls
--domain-filterDOMAIN_FILTERLimit to domains matching these suffixes (repeatable)
--exclude-domainsEXCLUDE_DOMAINSExclude domains matching these suffixes (repeatable)
--regex-domain-filterREGEX_DOMAIN_FILTERInclude domains matching this regex
--regex-domain-exclusionREGEX_DOMAIN_EXCLUSIONExclude domains matching this regex
--log-levelLOG_LEVELinfoLog level: debug, info, warning, error
--log-formatLOG_FORMATlogfmtLog format: logfmt, json
--read-timeoutREAD_TIMEOUT5sHTTP read timeout
--write-timeoutWRITE_TIMEOUT10sHTTP write timeout

OpenTelemetry

The webhook supports OpenTelemetry tracing via standard OTEL_* environment variables. Set service.version and deployment.environment.name via OTEL_RESOURCE_ATTRIBUTES:

env:
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: "http://otel-collector:4317"
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: "service.version=1.0.0,deployment.environment.name=production"

Development

Prerequisites: Go 1.26+, golangci-lint

make build        # lint, test, build
make test         # run unit tests with coverage
make race         # run tests with race detector
make lint         # run golangci-lint
make fmt          # format source code

Running locally

export TIDYDNS_USER='<username>'
export TIDYDNS_PASS='<password>'

go run main.go --tidydns-endpoint='https://dnsadmin.example.com/index.cgi' \
         --log-level='debug'

Releasing

Releases are managed by GoReleaser. Tag a commit and push:

git tag v1.2.3
git push origin v1.2.3

The CI pipeline builds binaries, creates multi-arch container images (linux/amd64, linux/arm64), and publishes them to ghcr.io/neticdk/external-dns-tidydns-webhook.