{"id":38582480,"url":"https://github.com/nixn/pdns-etcd3","last_synced_at":"2026-01-17T08:16:43.265Z","repository":{"id":57658639,"uuid":"67065496","full_name":"nixn/pdns-etcd3","owner":"nixn","description":"PowerDNS remote backend with ETCD v3 cluster as storage.","archived":false,"fork":false,"pushed_at":"2026-01-15T11:03:39.000Z","size":525,"stargazers_count":18,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-15T16:08:59.556Z","etag":null,"topics":["dns","etcd","go","pdns","pdns-etcd3","pdns-remote","powerdns"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nixn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-08-31T19:05:01.000Z","updated_at":"2026-01-15T11:03:43.000Z","dependencies_parsed_at":"2024-11-24T02:01:54.434Z","dependency_job_id":null,"html_url":"https://github.com/nixn/pdns-etcd3","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/nixn/pdns-etcd3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixn%2Fpdns-etcd3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixn%2Fpdns-etcd3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixn%2Fpdns-etcd3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixn%2Fpdns-etcd3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nixn","download_url":"https://codeload.github.com/nixn/pdns-etcd3/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixn%2Fpdns-etcd3/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28504359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dns","etcd","go","pdns","pdns-etcd3","pdns-remote","powerdns"],"created_at":"2026-01-17T08:16:43.168Z","updated_at":"2026-01-17T08:16:43.248Z","avatar_url":"https://github.com/nixn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pdns-etcd3\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/nixn/pdns-etcd3)](https://goreportcard.com/report/github.com/nixn/pdns-etcd3)\n[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/nixn/pdns-etcd3?include_prereleases\u0026sort=semver\u0026label=latest%20(pre-)release)](https://github.com/nixn/pdns-etcd3/releases)\n\nA [PowerDNS][pdns] [remote backend][pdns-remote] with [ETCD][] v3 cluster as storage.\nIt uses the [official client][etcd-client] to get the data from the cluster.\nResponses are authoritative for each zone found in the data.\nOnly the DNS class `IN` is supported, but that's because of the limitation of PowerDNS.\n\nThere is no stable release yet, even no beta. The latest release is [v0.2.0+0.1.1][],\nthe second development release, considered alpha quality. Any testing is appreciated.\n\n[pdns]: https://www.powerdns.com/\n[pdns-remote]: https://doc.powerdns.com/authoritative/backends/remote.html\n[etcd]: https://github.com/etcd-io/etcd/\n[etcd-client]: https://github.com/etcd-io/etcd/tree/main/client/v3\n[v0.2.0+0.1.1]: https://github.com/nixn/pdns-etcd3/releases/tag/v0.2.0%2B0.1.1\n\n## Features\n\n* Automatic serial for [`SOA` records](doc/ETCD-structure.md#soa) (based on the cluster revision).\n* Replication is handled by the ETCD cluster, no additional configuration is needed for using multiple authoritative PowerDNS servers.\n  * DNS responses are nearly instantly up-to-date (on every server instance!) after data changes by using a watcher into ETCD (multi-master)\n* [Multiple syntax possibilities](doc/ETCD-structure.md#syntax) for object-supported records\n* [Short syntax for single-value objects](doc/ETCD-structure.md#resource-record-values)\n  * or for the last value left when using defaults (e.g. [`target` in `SRV`](doc/ETCD-structure.md#srv))\n* [Default prefix for IP addresses](doc/ETCD-structure.md#a)\n  * overrideable per entry\n* Support for [custom records (types)](doc/ETCD-structure.md#resource-record-values), like those [supported by PowerDNS][pdns-qtypes] but unimplemented in pdns-etcd3\n* Support for [automatically appending zone name to unqualified domain names](doc/ETCD-structure.md#domain-name)\n* Override of domain name appended to unqualified names (instead of zone name)\n  * useful for [`PTR` records](doc/ETCD-structure.md#ptr) in reverse zones\n* [Multi-level defaults and options](doc/ETCD-structure.md#defaults-and-options), overridable\n* [Upgrade data structure](doc/ETCD-structure.md#upgrading) (if needed for new program version) without interrupting service\n* Run [standalone](#standalone-modes) for usage as a [Unix or HTTP connector][pdns-remote-usage]\n  * This could be needed for big data sets, because the initialization from PowerDNS is done lazily (at least in v4) on first request (which possibly could time out on \"big data\"…) :-(\n\n[pdns-qtypes]: https://doc.powerdns.com/authoritative/appendices/types.html\n\n#### Planned\n\n* Reduce redundancy in the data by automatically deriving corresponding data\n  * `A` ⇒ `PTR` (`in-addr.arpa`)\n  * `AAAA` ⇒ `PTR` (`ip6.arpa`)\n  * …\n* Support for defaults, syntax-checking and zone appending (and possibly more) in plain-string records (those which are also object-supported)\n* \"Collect record\", automatically combining A and/or AAAA records from \"server records\"\n  * e.g. `etcd.example.com` based on `etcd-1.example.com`, `etcd-2.example.com`, …\n* \"Labels\" for selectively applying defaults and/or options to record entries\n  * sth. like `com/example/-options-ptr` → `{\"auto-ptr\": true}` and `com/example/www/-options-collect` → `{\"collect\": …}` for `com/example/www-1/A+ptr+collect` without global options\n  * precedence betweeen QTYPE and id (id \u003e label \u003e QTYPE)\n* Support [JSON5][] by [flynn/json5](https://github.com/flynn/json5) (replace default JSON, because JSON5 is a superset of JSON)\n* Support [YAML][] by [go-yaml](https://github.com/go-yaml/yaml)\n* DNSSEC support ([PowerDNS DNSSEC-specific calls][pdns-dnssec])\n\n[pdns-dnssec]: https://doc.powerdns.com/authoritative/appendices/backend-writers-guide.html#dnssec-support\n[pdns-remote-usage]: https://doc.powerdns.com/authoritative/backends/remote.html#usage\n[json5]: https://json5.org/\n[yaml]: http://www.yaml.org/\n\n#### Optional\n\n* Support more encodings for values\n  * [EDN](https://github.com/edn-format/edn)\n    by [go-edn](https://github.com/go-edn/edn)\n  * [TOML](https://github.com/toml-lang/toml)\n    by [pelletier/go-toml](https://github.com/pelletier/go-toml)\n    or [BurntSushi/toml](https://github.com/BurntSushi/toml)\n  * …\n* [DNS update support](https://doc.powerdns.com/authoritative/appendices/backend-writers-guide.html#dns-update-support)\n* [Prometheus exporter](https://prometheus.io/docs/guides/go-application/)\n* ZeroMQ connector\n\n## Installation\n\n```sh\ngit clone https://github.com/nixn/pdns-etcd3.git\ncd pdns-etcd3\nmake\n```\n\nNOTE: `go build` will also work, but you will get a dynamically linked executable and incomplete version information in the binary.\nThe build command in `Makefile` produces a static build with setting the version string properly.\n\n## Usage\n\nOf course, you need an up and running ETCD v3 cluster and a PowerDNS installation.\n\nYou have to decide in which mode you want to use the backend: either the pipe mode or the unix mode.\n\n### Pipe mode\n\nIn pipe mode the backend is launched by PowerDNS dynamically and communicates with it via standard input and output.\nAll the configuration options must be given in the PowerDNS configuration file. But since PowerDNS (at least as of v4)\ninitiates the backend lazily, the 'initialize' call occurs with the first (client) request and the backend has to be fast\nenough to connect to ETCD, read all data, and reply to this first request. This can be too long, if there is much data to read.\n\nExample PowerDNS configuration file:\n```\nlaunch=remote\nremote-connection-string=pipe:command=/path/to/pdns-etcd3[,pdns-version=3|4|5][,\u003cconfig\u003e][,prefix=\u003cstring\u003e][,timeout=\u003cinteger\u003e][,log-\u003clevel\u003e=\u003ccomponents\u003e]\n# since in pipe mode every instance connects to ETCD and loads the data for itself (uses memory), possibly do this:\ndistributor-threads=1\n```\n\n`\u003cconfig\u003e` is one of `config-file=...` or `endpoints=...` (see \"Parameters\" below for details on the value).\n`config-file` overrides `endpoints`.\n\n### Standalone mode(s)\n\nAll other modes are so-called \"standalone\" modes: the backend must be launched outside of PowerDNS (manually, e.g. as a system service).\nThe standalone mode creates a listening socket and waits for connections (from PowerDNS).\nIt takes the ETCD related parameters from the command line and connects to it right after starting up.\nThen it accepts connections on the socket and serves them.\nIf the standalone mode begins with an 'initialize' call, only the non-ETCD parameters are available to it.\n\nThe data is loaded only once (uses memory only once). The data is loaded before accepting connections from PowerDNS,\nso it is available directly after a PowerDNS instance has connected.\nIt is okay to have parallel accesses to the instance, the data access is protected by mutexes (including updates).\n\nA standalone mode is started by passing the `-standalone=\u003cconnector-url\u003e` flag to pdns-etcd3.\nThe `\u003cconnector-url\u003e` must be a valid URL, specific for each mode.\n\n#### Unix\n\nThe unix mode uses a UNIX domain socket, thus it can only run on the same system as PowerDNS.\nThe `\u003cconnector-url\u003e` looks like:\n```text\nunix:///path/to/pdns-etcd3-socket[?relative=\u003cbool\u003e]\n```\nIt gives the path to the socket file (which is then used in the PowerDNS configuration, see below).\n`relative` is false by default, so the path is taken as an absolute path.\nWhen set to true, the leading slash is ignored and the path is taken as a relative path.\n\nThe unix mode takes an 'initialize' call, so one can pass parameters to it, which are defined in the PowerDNS configuration.\n\nExample PowerDNS configuration file:\n```text\nlaunch=remote\nremote-connection-string=unix:path=/path/to/pdns-etcd3-socket[,pdns-version=3|4|5][,log-\u003clevel\u003e=\u003ccomponents\u003e]\ndistributor-threads=3\n```\n\n#### HTTP\n\nThe HTTP mode uses an HTTP listening socket, thus can serve PowerDNS instances from virtually everywhere,\nbased on the listening address. The `\u003cconnector-url\u003e` looks like:\n```text\nhttp://\u003caddress\u003e:\u003cport\u003e\n```\nOne has to give both, `\u003caddress\u003e` and `\u003cport\u003e`. To listen on all interfaces, the URL could look like: `http://0.0.0.0:8053`.\n\nThe HTTP mode does not take an 'initialize' call.\n\nIn the PowerDNS configuration, the parameters `post` and `post_json` must be both set to true.\nOtherwise the requests would be rejected.\n\nExample PowerDNS configuration file:\n```text\nlaunch=remote\nremote-connection-string=http:url=http://localhost:8053/,post=yes,post_json=yes\n```\n\nBecause there is no 'initialize' call, the version of PowerDNS cannot be known (and is not passed in the requests).\nBut it is assumed to be 4+ (i.e. not 3), because the HTTP support was not present in PDNSv3.\n\n### Parameters\n\nAll parameter keys must be given exactly as denoted here (no case modifications). The ETCD related parameters in standalone mode\nare given as command line \"options\", starting with a `-`: e.g. `-config-file=...`.\n\nThe parameters in detail (the ETCD related parameters, which have to be passed as command line argument in standalone mode,\nare tagged by *#STANDALONE*):\n\n* `config-file=/path/to/etcd.conf` *#STANDALONE*\u003cbr\u003e\n  The path to an ETCD (client) configuration file, as accepted by the official client\n  (see [etcd/client/v3/config.go](https://github.com/etcd-io/etcd/blob/master/client/v3/config.go), TODO find documentation)\u003cbr\u003e\n  TLS and authentication is only possible when using such a configuration file.\u003cbr\u003e\n  Overrides `endpoints` parameter. Defaults to not set.\n* `endpoints=\u003cIP:Port\u003e[|\u003cIP:Port\u003e|...]` *#STANDALONE*\u003cbr\u003e\n  For a simple connection use the endpoints given here. `endpoints` accepts hostnames too (instead of `IP`), but be sure\n  they are resolvable before PowerDNS has started.\u003cbr\u003e\n  Defaults to `[::1]:2379|127.0.0.1:2379`.\n* `prefix=\u003cstring\u003e` *#STANDALONE*\u003cbr\u003e\n  Every entry in ETCD will be prefixed with that. It is not interpreted or changed in any way, also the data watcher uses it,\n  so any other keys under another prefix do not affect DNS data.\u003cbr\u003e\n  Tip: Let the prefix start and end with `/`, so you can use [etcdkeeper][] for easier web-based data management.\u003cbr\u003e\n  There is no default (= empty).\n* `timeout=\u003cduration\u003e` *#STANDALONE* or\u003cbr\u003e\n  `timeout=\u003cinteger\u003e` *config file* (in milliseconds, e.g. `1500` for 1.5 seconds)\u003cbr\u003e\n  An optional parameter which sets the dial timeout to ETCD. Must be a positive value (\u003e= 1ms).\u003cbr\u003e\n  Defaults to 2 seconds.\n* `pdns-version=3|4|5`\u003cbr\u003e\n  The (major) PowerDNS version. Version 3 and 4 have incompatible protocols with the backend, so one must use the proper one.\n  Version 5 is accepted, but works currently the same as 4 (no relevant API changes yet).\u003cbr\u003e\n  Defaults to `4`.\n* `log-\u003clevel\u003e=\u003ccomponents\u003e` *#STANDALONE* and *config file*\u003cbr\u003e\n  Sets the logging level of `\u003ccomponents\u003e` to `\u003clevel\u003e` (see below for values). `\u003ccomponents\u003e` is one or more of the\n  component names, separated by `+`. This parameter can be \"repeated\" for different logging levels.\n  In unix mode, the levels are set separately for the program and the clients (PowerDNS connections).\u003cbr\u003e\n  Example: `log-debug=main+pdns,log-trace=etcd+data`\u003cbr\u003e\n  Defaults to `info` for all components.\n\nOne can see all available command-line (standalone) parameters with a short description, when running `pdns-etcd3 -help`.\n\n[etcdkeeper]: https://github.com/evildecay/etcdkeeper\n\n### ETCD structure\n\nSee [ETCD structure](doc/ETCD-structure.md). The structure lies beneath the `prefix` parameter (see above).\n\n## Compatibility\n\npdns-etcd3 is tested on PowerDNS versions 3.y.z and different 4.y.z, and uses an ETCD v3 cluster (API 3.0 or higher).\nIt's currently only one version of each minor (.y), but most likely all (later) \"patch\" versions (.z) are compatible.\nTherefore, each release shall state which exact versions were used for testing,\nso one can be sure to have a working combination for deploying, when using those (tested) versions.\n\n## Testing / Debugging\n\nThere is much logging in the program for being able to test and debug it properly.\nIt is structured and leveled, utilizing [logrus][]. The structure consists of different components,\nnamely `main`, `pdns`, `etcd` and `data`; the (seven) logging levels are [taken from logrus][logrus-levels].\nFor each component an own logging level can be set, so that one can debug only the component(s) of interest.\nIn the standalone modes the components are \"doubled\"; there is the program side with its components (main, etcd, data) and\nthe (PDNS) client side (main, pdns), which can be configured separately. In pipe mode there is only one of each component.\n\nThe components in detail:\n* `main` - The main thread / loop of the program, e.g. setting up logging, creating data objects, processing signals and events, etc.\n* `pdns` - The communication with PowerDNS, e.g. incoming requests and sending results.\n* `etcd` - The communication with ETCD, e.g. real queries against it, connection issues, watcher, etc.\n* `data` - Everything concerning the values (records, ...), parsing data from ETCD, searching records for requests etc.\n\nThe levels in detail:\n* `panic` - Something like the world's end. Actually not used.\n* `fatal` - Errors which prevent the program to continue service. After a fatal error the program exits. (Mostly in `main` component.)\n* `error` - Errors which don't prevent the program to continue service. Different meanings for different components.\n* `warning` (or `warn`) - Not errors, but situations where it could be done better. An admin should take care of those.\n* `info` - Useful information on the program, something like \"initialized, ready for service\". This is the default level for each component.\n* `debug` - \"Big steps\", like \"sending request to ETCD\", \"Handling event\" or \"default value not found for X\"\n* `trace` - Small steps and all values, e.g. \"found default value for X in Y\" or \"record: www.example.com./A#some-id = 192.0.2.12\"\n\n[logrus]: https://github.com/Sirupsen/logrus\n[logrus-levels]: https://github.com/sirupsen/logrus#level-logging\n\n## License\n\nCopyright © 2016-2026 nix \u003chttps://keybase.io/nixn\u003e\n\nDistributed under the Apache 2.0 license, available in the file [LICENSE](LICENSE).\n\n## Donations\n\nIf you like pdns-etcd3, please consider donating to support the further development. Thank you!\n\nBitcoin (BTC): `1pdns4U2r4JqkzsJRpTEYNirTFLtuWee9`\u003cbr\u003e\nMonero (XMR): `4CjXUfpdcba5G5z1LXAx3ngoDtAHoFGdpJWvCayULXeaEhA4QvJEHdR7Xi3ptsbhSfGcSpdBHbK4CgyC6Qcwy5Rt2GGDfQCM7PcTgfEQ5Q`\u003cbr\u003e\nEthereum (ETH): `0x003D87efb7069e875a8a1226c9DadaC03dE1f779`\n\nThese addresses are dedicated to pdns-etcd3 development.\nFor my general development, other projects and personal donation addresses see my profile or my web page.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixn%2Fpdns-etcd3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnixn%2Fpdns-etcd3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixn%2Fpdns-etcd3/lists"}