|
|
||
|---|---|---|
| .forgejo | ||
| ci | ||
| src | ||
| .gitignore | ||
| Dockerfile | ||
| LICENSE | ||
| openapi.json | ||
| README.md | ||
| renovate.json | ||
| Taskfile.yml | ||
Domeneshop Webhook for ExternalDNS
A lightweight webhook that integrates Domeneshop DNS with Kubernetes ExternalDNS.
🚀 Key Features
- Automatic DNS record management for Kubernetes services and gateways.
- CNAME Flattening: Automatically handles CNAME records at the zone apex to avoid conflicts.
- Supports A, AAAA, CNAME, and TXT records.
- Simple deployment as a sidecar container.
- Health and readiness probes.
- Configurable TLS and CORS support.
📋 Quick Start
Prerequisites
- A Kubernetes cluster with ExternalDNS installed.
- Domeneshop API credentials (get yours here).
Deployment
-
Create a Kubernetes secret for your Domeneshop credentials:
kubectl create secret generic external-dns-domeneshop-webhook \ --from-literal=DOMENESHOP_API_TOKEN=<your_api_token> \ --from-literal=DOMENESHOP_API_SECRET=<your_api_secret> -
Configure ExternalDNS to use the webhook. Below is a sample
values.yamlfor the ExternalDNS Helm chart.Note: Your
extraArgsmay vary depending on your specific setup (e.g., if you use Ingress instead of Gateway API).# external-dns-domeneshop-values.yaml fullnameOverride: external-dns-domeneshop # Add arguments for your environment. The example below is for Gateway API. extraArgs: - --gateway-label-filter=app.kubernetes.io/name in (gateway-external) - --ignore-hostname-annotation - --fqdn-template=external.example.com # Configure the webhook provider provider: name: webhook webhook: image: repository: code.252.no/pub/external-dns-domeneshop-webhook tag: v0.7.2 # Use the latest version env: - name: PORT value: "8080" - name: TOKEN valueFrom: secretKeyRef: name: external-dns-domeneshop-webhook key: DOMENESHOP_API_TOKEN - name: SECRET valueFrom: secretKeyRef: name: external-dns-domeneshop-webhook key: DOMENESHOP_API_SECRET # Optional: Set log level to 'debug' for more verbose output # - name: LOG_LEVEL # value: debug ports: - containerPort: 8080 name: http livenessProbe: httpGet: path: /healthz port: http readinessProbe: httpGet: path: /readyz port: http # Recommended settings for optimal performance triggerLoopOnEvent: true policy: sync # Configure your sources and domain filters sources: - gateway-httproute txtOwnerId: k8s txtPrefix: kube. domainFilters: - "example.com" -
Install or upgrade ExternalDNS with your values:
helm upgrade my-release external-dns/external-dns \ --install \ -f external-dns-domeneshop-values.yaml
⚙️ Configuration
The webhook is configured entirely through environment variables:
| Variable | Description | Default |
|---|---|---|
TOKEN |
Domeneshop API token | Required |
SECRET |
Domeneshop API secret | Required |
PORT |
Server port | 8080 |
TLS_CERT_FILE |
Path to a TLS certificate file | "" |
TLS_KEY_FILE |
Path to a TLS key file | "" |
ALLOWED_ORIGINS |
CORS allowed origins (comma-separated) | * |
LOG_LEVEL |
Log level (debug, info, warn, error) |
info |
🔍 Implementation Details
Architecture
┌─────────────┐ ┌────────────────┐ ┌──────────────────┐
│ ExternalDNS │────▶│ Webhook Server │────▶│ Domeneshop API │
└─────────────┘ └────────────────┘ └──────────────────┘
CNAME Flattening (Zone Apex)
Domeneshop, in compliance with DNS RFCs, does not allow a CNAME record at the zone apex (e.g., example.com) if other records (like NS or SOA) exist. Attempting to create one will result in a 409 Conflict error from the API.
To solve this, the webhook automatically performs CNAME flattening. When ExternalDNS requests a CNAME for a zone apex, the webhook:
- Resolves the CNAME target to its underlying IP address(es).
- Creates
A(for IPv4) and/orAAAA(for IPv6) records instead.
This allows you to point your root domain to another service without violating DNS rules.
🤝 Contributing
Contributions are welcome! Please feel free to open an issue or submit a merge request.
📜 License
This project is licensed under the AGPL-3.0-only license. See the LICENSE file for details.
🤖 Dependency Management
This project uses Renovate to keep dependencies up-to-date. See renovate.json for the configuration.
🧪 Development
To run the webhook locally for development:
-
Set environment variables with your Domeneshop API credentials:
export DOMENESHOP_API_TOKEN="your_api_token" export DOMENESHOP_API_SECRET="your_api_secret" -
Run the webhook:
go run ./src/main.goThe server will start on
http://localhost:8080. -
Test with ExternalDNS:
You can configure a local ExternalDNS instance to point to your development server. To expose your local server to your cluster, a tool like ngrok can be used.
Update your
external-dns-domeneshop-values.yamlwith the public URL from ngrok:# ... provider: webhook: url: "https://your-ngrok-url.ngrok.io" # ...Then apply the changes:
helm upgrade my-release external-dns/external-dns \ -f external-dns-domeneshop-values.yaml