Custom DNS Provider Plugins
Charon supports extending its DNS provider capabilities through a plugin system. This guide covers installation and usage of custom DNS provider plugins.
Platform Limitations
Important: Go plugins are only supported on Linux and macOS. Windows users must rely on built-in DNS providers.
- Supported: Linux (x86_64, ARM64), macOS (x86_64, ARM64)
- Not Supported: Windows (any architecture)
Security Considerations
Critical Security Warnings
⚠️ Plugins Execute In-Process
Custom plugins run directly within the Charon process with full access to:
- All system resources and memory
- Database credentials
- API tokens and secrets
- File system access with Charon's permissions
Only install plugins from trusted sources.
Security Best Practices
- Verify Plugin Source: Only download plugins from official repositories or trusted developers
- Check Signatures: Use signature verification (see Configuration section)
- Review Code: If possible, review plugin source code before building
- Secure Permissions: Plugin directory must not be world-writable (enforced automatically)
- Isolate Environment: Consider running Charon in a container with restricted permissions
- Regular Updates: Keep plugins updated to receive security patches
Signature Verification
Configure signature verification in your Charon configuration:
plugins:
directory: /path/to/plugins
allowed_signatures:
powerdns: "sha256:abc123def456..."
custom-provider: "sha256:789xyz..."
To generate a signature for a plugin:
sha256sum powerdns.so
# Output: abc123def456... powerdns.so
Installation
Prerequisites
- Charon must be built with CGO enabled (
CGO_ENABLED=1) - Go version must match between Charon and plugins (critical for compatibility)
- Plugin directory must exist with secure permissions
Installation Steps
-
Obtain the Plugin File
Download the
.sofile for your platform:curl https://example.com/plugins/powerdns-linux-amd64.so -O powerdns.so -
Verify Plugin Integrity (Recommended)
Check the SHA-256 signature:
sha256sum powerdns.so# Compare with published signature -
Copy to Plugin Directory
sudo mkdir -p /etc/charon/pluginssudo cp powerdns.so /etc/charon/plugins/sudo chmod 755 /etc/charon/plugins/powerdns.sosudo chown root:root /etc/charon/plugins/powerdns.so -
Configure Charon
Edit your Charon configuration file:
plugins:directory: /etc/charon/plugins# Optional: Enable signature verificationallowed_signatures:powerdns: "sha256:your-signature-here" -
Restart Charon
sudo systemctl restart charon -
Verify Plugin Loading
Check Charon logs:
sudo journalctl -u charon -f | grep -i pluginExpected output:
INFO Loaded DNS provider plugin type=powerdns name="PowerDNS" version="1.0.0"INFO Loaded 1 external DNS provider plugins (0 failed)
Docker Installation
When running Charon in Docker:
-
Mount Plugin Directory
# docker-compose.ymlservices:charon:image: charon:latestvolumes:- ./plugins:/etc/charon/plugins:roenvironment:- PLUGIN_DIR=/etc/charon/plugins -
Build with Plugins
Alternatively, include plugins in your Docker image:
FROM charon:latestCOPY plugins/*.so /etc/charon/plugins/
Using Custom Providers
Once a plugin is installed and loaded, it appears in the DNS provider list alongside built-in providers.
Discovering Loaded Plugins via API
Query available provider types to see all registered providers (built-in and plugins):
curl https://charon.example.com/api/v1/dns-providers/types \
-H "Authorization: Bearer YOUR-TOKEN"
Response:
{
"types": [
{
"type": "cloudflare",
"name": "Cloudflare",
"description": "Cloudflare DNS provider",
"documentation_url": "https://developers.cloudflare.com/api/",
"is_built_in": true,
"fields": [...]
},
{
"type": "powerdns",
"name": "PowerDNS",
"description": "PowerDNS Authoritative Server with HTTP API",
"documentation_url": "https://doc.powerdns.com/authoritative/http-api/",
"is_built_in": false,
"fields": [...]
}
]
}
Key fields:
| Field | Description |
|---|---|
is_built_in | true = compiled into Charon, false = external plugin |
fields | Credential field specifications for the UI form |
Via Web UI
- Navigate to Settings → DNS Providers
- Click Add Provider
- Select your custom provider from the dropdown
- Enter required credentials
- Click Test Connection to verify
- Save the provider
Via API
curl -X POST https://charon.example.com/api/admin/dns-providers \
-H "Authorization: Bearer YOUR-TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "powerdns",
"credentials": {
"api_url": "https://pdns.example.com:8081",
"api_key": "your-api-key",
"server_id": "localhost"
}
}'
Example: PowerDNS Plugin
The PowerDNS plugin demonstrates a complete DNS provider implementation.
Required Credentials
- API URL: PowerDNS HTTP API endpoint (e.g.,
https://pdns.example.com:8081) - API Key: X-API-Key header value for authentication
Optional Credentials
- Server ID: PowerDNS server identifier (default:
localhost)
Configuration Example
{
"type": "powerdns",
"credentials": {
"api_url": "https://pdns.example.com:8081",
"api_key": "your-secret-key",
"server_id": "ns1"
}
}
Caddy Integration
The plugin automatically configures Caddy's DNS challenge for Let's Encrypt:
{
"name": "powerdns",
"api_url": "https://pdns.example.com:8081",
"api_key": "your-secret-key",
"server_id": "ns1"
}
Timeouts
- Propagation Timeout: 60 seconds
- Polling Interval: 2 seconds
Plugin Management
Admin only. Enabling, disabling, reloading, and unloading plugins requires an administrator account. Standard users can view the list of installed plugins but cannot change which ones are active.
Listing Loaded Plugins
Via Types Endpoint (Recommended):
Filter for plugins using is_built_in: false:
curl https://charon.example.com/api/v1/dns-providers/types \
-H "Authorization: Bearer YOUR-TOKEN" | jq '.types[] | select(.is_built_in == false)'
Via Plugins Endpoint:
Get detailed plugin metadata including version and author:
curl https://charon.example.com/api/admin/plugins \
-H "Authorization: Bearer YOUR-TOKEN"
Response:
{
"plugins": [
{
"type": "powerdns",
"name": "PowerDNS",
"description": "PowerDNS Authoritative Server with HTTP API",
"version": "1.0.0",
"author": "Charon Community",
"is_built_in": false,
"go_version": "go1.23.4",
"interface_version": "v1"
}
]
}
Reloading Plugins
To reload plugins without restarting Charon:
curl -X POST https://charon.example.com/api/admin/plugins/reload \
-H "Authorization: Bearer YOUR-TOKEN"
Note: Due to Go runtime limitations, plugin code remains in memory even after unloading. A full restart is required to completely unload plugin code.
Unloading a Plugin
curl -X DELETE https://charon.example.com/api/admin/plugins/powerdns \
-H "Authorization: Bearer YOUR-TOKEN"
Troubleshooting
Plugin Not Loading
Check Go Version Compatibility:
go version
# Must match the version shown in plugin metadata
Check Plugin File Permissions:
ls -la /etc/charon/plugins/
# Should be 755 or 644, not world-writable
Check Charon Logs:
sudo journalctl -u charon -n 100 | grep -i plugin
Common Errors
plugin was built with a different version of Go
Cause: Plugin compiled with different Go version than Charon
Solution: Rebuild plugin with matching Go version or rebuild Charon
plugin not in allowlist
Cause: Signature verification enabled, but plugin not in allowed list
Solution: Add plugin signature to allowed_signatures configuration
signature mismatch
Cause: Plugin file signature doesn't match expected value
Solution: Verify plugin file integrity, re-download if corrupted
missing 'Plugin' symbol
Cause: Plugin doesn't export required Plugin variable
Solution: Rebuild plugin with correct exported symbol (see developer guide)
interface version mismatch
Cause: Plugin built against incompatible interface version
Solution: Update plugin to match Charon's interface version
Directory Permission Errors
If Charon reports "directory has insecure permissions":
# Fix directory permissions
sudo chmod 755 /etc/charon/plugins
# Ensure not world-writable
sudo chmod -R o-w /etc/charon/plugins
Performance Considerations
- Startup Time: Plugin loading adds 10-50ms per plugin to startup time
- Memory: Each plugin uses 1-5MB of additional memory
- Runtime: Plugin calls have minimal overhead (nanoseconds)
Compatibility Matrix
| Charon Version | Interface Version | Go Version Required |
|---|---|---|
| 1.0.x | v1 | 1.23.x |
| 1.1.x | v1 | 1.23.x |
| 2.0.x | v2 | 1.24.x |
Always use plugins built for your Charon interface version.
Support
Getting Help
- GitHub Discussions: https://github.com/Wikid82/charon/discussions
- Issue Tracker: https://github.com/Wikid82/charon/issues
- Documentation: https://docs.charon.example.com
Reporting Issues
When reporting plugin issues, include:
- Charon version and Go version
- Plugin name and version
- Operating system and architecture
- Complete error logs
- Plugin metadata (from API response)
See Also
- Plugin Security Guide
- Plugin Development Guide (internal document)
- DNS Provider Configuration
- Security Best Practices