2.8 KiB
dns-sync modular
A plugin-based DNS reconciliation service.
Plugin contract
The reconciliation runtime is adapter-based.
Adapter plugins expose:
Pluginconfigured_endpoints(config)
Each adapter declares object-specific discovery, apply, and verification
capabilities. Built-in adapters live under dns_sync/plugins/adapters/.
External adapters are loaded from DNS_SYNC_PLUGIN_PATH and must be
explicitly enabled through ENABLED_PLUGINS.
Plugins
The generic reconciliation engine uses adapter plugins.
Built-in adapters:
npm- Nginx Proxy Manager proxy hosts and certificates
External adapters are loaded from DNS_SYNC_PLUGIN_PATH and must also be
explicitly enabled through ENABLED_PLUGINS.
Example:
ENABLED_PLUGINS=npm,verizon
DNS_SYNC_PLUGIN_PATH=/plugins
The Verizon adapter lives under external_plugins/verizon and is deliberately
not copied into the dns-sync container image. The external plugin directory is
mounted read-only at runtime.
Container runtime
The container periodically executes the generic reconciliation engine:
python -m dns_sync reconcile
The default container mode is read-only.
SYNC_INTERVAL=1
DNS_SYNC_APPLY=false
DNS_SYNC_STATE_DB=/var/lib/dns-sync/state.sqlite3
DNS_SYNC_PLUGIN_PATH=/plugins
ENABLED_PLUGINS=npm,verizon
SYNC_INTERVAL is expressed in minutes. The interval begins after each
reconciliation completes, so runs do not overlap.
To permit planned changes to be applied and verified:
DNS_SYNC_APPLY=true
An optional mutation budget can be specified:
DNS_SYNC_MAX_CHANGES=10
When DNS_SYNC_APPLY=false, reconciliation still performs discovery,
normalization, desired-state reconciliation, planning, and state persistence,
but no endpoint mutations are executed.
The SQLite database should be stored on persistent storage.
External plugins should be mounted read-only at /plugins.
Main environment
NPM_ENDPOINTS=192.168.1.3,192.168.1.4,192.168.1.5
PROXY_API_PORT=81
PROXY_API_SCHEME=http
DNS_TARGET_IP=192.168.1.101
VERIZON_ENDPOINTS=192.168.1.1
DOMAIN_MATCHING=false
DOMAIN=example.com
NPM_IDENTITY=...
NPM_SECRET=...
ROUTER_PASSWORD=...
Domain filtering
Filtering is performed centrally after adapter discovery and before reconciliation, so endpoint-specific adapters get identical behavior.
DOMAIN_MATCHING=true
DOMAIN=example.com
This includes the apex and every subdomain:
example.com
app.example.com
deep.app.example.com
*.example.com
It excludes unrelated names such as:
example.net
notexample.com
example.com.evil.net
When DOMAIN_MATCHING=false, DOMAIN is ignored and all discovered records are
eligible for reconciliation.
When DOMAIN_MATCHING=true, DOMAIN is required.