{"id":13646563,"url":"https://github.com/skynetservices/skydns","last_synced_at":"2025-12-30T03:38:09.135Z","repository":{"id":16454480,"uuid":"19206385","full_name":"skynetservices/skydns","owner":"skynetservices","description":"DNS service discovery for etcd","archived":false,"fork":true,"pushed_at":"2021-03-21T11:57:30.000Z","size":985,"stargazers_count":2200,"open_issues_count":61,"forks_count":304,"subscribers_count":102,"default_branch":"master","last_synced_at":"2025-01-02T04:15:14.562Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"miekg/skydns2","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skynetservices.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}},"created_at":"2014-04-27T14:25:30.000Z","updated_at":"2025-01-02T02:55:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/skynetservices/skydns","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skynetservices%2Fskydns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skynetservices%2Fskydns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skynetservices%2Fskydns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skynetservices%2Fskydns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skynetservices","download_url":"https://codeload.github.com/skynetservices/skydns/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250136649,"owners_count":21380871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-08-02T01:02:59.189Z","updated_at":"2025-12-17T21:21:37.004Z","avatar_url":"https://github.com/skynetservices.png","language":"Go","funding_links":[],"categories":["Orchestration \u0026 Management","others","Go","Capabilities","Infrastructure"],"sub_categories":["Configuration \u0026 Discovery","Configuration and Discovery"],"readme":"# SkyDNS [![Build Status](https://travis-ci.org/skynetservices/skydns.png?branch=master)](https://travis-ci.org/skynetservices/skydns)\n*Version 2.5.3a*\n\nSkyDNS is a distributed service for announcement and discovery of services built\non top of [etcd](https://github.com/coreos/etcd). It utilizes DNS queries to\ndiscover available services. This is done by leveraging SRV records in DNS, with\nspecial meaning given to subdomains, priorities and weights.\n\nThis is the original [announcement blog\npost](http://blog.gopheracademy.com/skydns) for version 1. Since then, SkyDNS\nhas seen some changes, most notably the ability to use etcd as a backend.\n[Here you can find the SkyDNS2 announcement](http://miek.nl/posts/2014/Jun/08/announcing%20SkyDNS%20version%202/).\n\n\n# Changes since version 1\n\nSkyDNS2:\n\n* Does away with Raft and uses etcd (which uses raft).\n* Makes it possible to query arbitrary domain names.\n* Is a thin layer above etcd, that translates etcd keys and values to the DNS.\n* Does DNSSEC with NSEC3 instead of NSEC.\n\nNote that bugs in SkyDNS1 will still be fixed, but the main development effort\nwill be focussed on version 2. [Version 1 of SkyDNS can be found\nhere](https://github.com/skynetservices/skydns1).\n\n\n## Setup / Install\n\nDownload/compile and run etcd. See the documentation for etcd at \u003chttps://github.com/coreos/etcd\u003e.\n\nThen get and compile SkyDNS:\n\n    go get github.com/skynetservices/skydns\n    cd $GOPATH/src/github.com/skynetservices/skydns\n    go build -v\n\nSkyDNS' configuration is stored *in* etcd: but there are also flags and\nenvironment variables you can set. To start SkyDNS, set the etcd machines with\nthe environment variable ETCD_MACHINES:\n\n    export ETCD_MACHINES='http://192.168.0.1:4001,http://192.168.0.2:4001'\n    ./skydns\n\nIf `ETCD_MACHINES` is not set, SkyDNS will default to using\n`http://127.0.0.1:4001` to connect to etcd. Or you can use the flag `-machines`.\nAuto-discovering new machines added to the network can be enabled by enabling\nthe flag `-discover`.\n\nOptionally (but recommended) give it a nameserver:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dns/ns/ns1 \\\n        -d value='{\"host\":\"192.168.0.1\"}'\n\nAlso see the section \"NS Records\".\n\n\n## Configuration\n\nSkyDNS' configuration is stored in etcd as a JSON object under the key\n`/skydns/config`. The following parameters may be set:\n\n* `dns_addr`: IP:port on which SkyDNS should listen, defaults to `127.0.0.1:53`.\n* `domain`: domain for which SkyDNS is authoritative, defaults to `skydns.local.`.\n* `dnssec`: enable DNSSEC\n* `hostmaster`: hostmaster email address to use.\n* `local`: optional unique value for this skydns instance, default is none. This is returned\n    when queried for `local.dns.skydns.local`.\n* `round_robin`: enable round-robin sorting for A and AAAA responses, defaults to true.\n    Note that packets containing more than one CNAME are exempt from this (see issue #128 on Github).\n* `nameservers`: forward DNS requests to these (recursive) nameservers (array of IP:port combination),\n    when not authoritative for a domain. This defaults to the servers listed in `/etc/resolv.conf`. Also\n    see `no_rec`.\n* `no_rec`: never (ever) provide a recursive service (i.e. forward to the servers provided in -nameservers).\n* `read_timeout`: network read timeout, for DNS and talking with etcd.\n* `ttl`: default TTL in seconds to use on replies when none is set in etcd, defaults to 3600.\n* `min_ttl`: minimum TTL in seconds to use on NXDOMAIN, defaults to 30.\n* `scache`: the capacity of the DNSSEC signature cache, defaults to 10000 signatures if not set.\n* `rcache`: the capacity of the response cache, defaults to 0 messages if not set.\n* `rcache_ttl`: the TTL of the response cache, defaults to 60 if not set.\n* `ndots`: how many labels a name should have before we allow forwarding. Default to 2.\n* `systemd`: bind to socket(s) activated by systemd (ignores -addr).\n* `path-prefix`: backend(etcd) path prefix, defaults to skydns (i.e. if it is set to `mydns`, the SkyDNS's configuration object should be stored under the key `/mydns/config`).\n* `etcd3`: flag that toggles the etcd version 3 support by skydns during runtime. Defaults to false.\n\nTo set the configuration, use something like:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/config \\\n        -d value='{\"dns_addr\":\"127.0.0.1:5354\",\"ttl\":3600, \"nameservers\": [\"8.8.8.8:53\",\"8.8.4.4:53\"]}'\n\nSkyDNS needs to be restarted for configuration changes to take effect. This\nmight change, so that SkyDNS can re-read the config from etcd after a HUP\nsignal.\n\nYou can also use the command line options, however the settings in etcd take\nprecedence.\n\n\n### Commandline flags\n\n* `-addr`: used to specify the address to listen on (note: this will be changed into `-dns_addr` to match the json.\n* `-local`: used to specify a unique service for this SkyDNS instance. This should point to a (unique) domain into etcd, when\n    SkyDNS receives a query for the name `local.dns.skydns.local` it will fetch this service and return it.\n    For instance: `-local e2016c14-fbba-11e3-ae08-10604b7efbe2.dockerhosts.skydns.local` and then\n\n        curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dockerhosts/e2016c14-fbba-11e3-ae08-10604b7efbe2 \\\n            -d value='{\"host\":\"10.1.1.16\"}'\n\n    To register the local IP address. Now when SkyDNS receives a query for local.dns.skydns.local it will fetch the above\n    key and returns that one service. In other words skydns will substitute `e2016c14-fbba-11e3-ae08-10604b7efbe2.dockerhosts.skydns.local`\n    for `local.dns.skydns.local`. This follows the same rules as the other services, so it can also be an external names, which\n    will be resolved.\n\n    Also see the section Host Local Values.\n\n\n### Environment Variables\n\nSkyDNS uses these environment variables:\n\n* `ETCD_MACHINES` - list of etcd machines, \"http://localhost:4001,http://etcd.example.com:4001\". Overwrite with `-machines` string flag.\n* `ETCD_TLSKEY` - path of TLS client certificate - private key. Overwrite with `-tls-key` string flag.\n* `ETCD_TLSPEM` - path of TLS client certificate - public key. Overwrite with `-tls-pem` string flag.\n* `ETCD_CACERT` - path of TLS certificate authority public key. Overwrite with `-ca-cert` string flag.\n* `ETCD_USERNAME` - username used for basic auth. Overwrite with `-username` string flag.\n* `ETCD_PASSWORD` - password used for basic auth. Overwrite with `-password` string flag.\n* `SKYDNS_ADDR` - specify address to bind to. Overwrite with `-addr` string flag.\n* `SKYDNS_DOMAIN` - set a default domain if not specified by etcd config. Overwrite with `-domain` string flag.\n* `SKYDNS_NAMESERVERS` - set a list of nameservers to forward DNS requests to\n  when not authoritative for a domain, \"8.8.8.8:53,8.8.4.4:53\". Overwrite with `-nameservers` string flag.\n* `SKYDNS_PATH_PREFIX` - backend(etcd) path prefix, defaults to skydns (i.e. if it is set to `mydns`, the SkyDNS's configuration object should be stored under the key `/mydns/config`). Overwrite with `-path-prefix` string flag.\n* `SKYDNS_SYSTEMD`: set to `true` to bind to socket(s) activated by systemd (ignores SKYDNS_ADDR). Overwrite with `-systemd` bool flag.\n* `SKYDNS_NDOTS`: how many labels a name should have before we allow forwarding. Default to 2.\n\nFor [Prometheus](http://prometheus.io/) the following environment variables\nare available:\n\n* `PROMETHEUS_PORT`: port where the HTTP server for prometheus will run.\n* `PROMETHEUS_PATH`: path for the metrics, defaults to `/metrics`.\n* `PROMETHEUS_NAMESPACE`: namespace used in the metrics, no default.\n* `PROMETHEUS_SUBSYSTEM`: subsystem used in the metric, defaults to `skydns`.\n\nIf `PROMETHEUS_PORT` is set to an integer larger than 0, Prometheus support will\nbe enabled.\n\nCurrent counters are:\n\n*  `dns_request_count_total`, total count of request made against SkyDNS.\n*  `dns_request_duration_seconds`, duration of the request handling in seconds.\n*  `dns_response_size_bytes`, size of the repsonses in bytes.\n*  `dns_error_count_total`, total count of responses containing errors.\n*  `dns_cachemiss_count_total`, total count of cache misses.\n\n### SSL Usage and Authentication with Client Certificates\n\nIn order to connect to an SSL-secured etcd, you will at least need to set\nETCD_CACERT to be the public key of the Certificate Authority which signed the\nserver certificate.\n\nIf the SSL-secured etcd expects client certificates to authorize connections,\nyou also need to set ETCD_TLSKEY to the *private* key of the client, and\nETCD_TLSPEM to the *public* key of the client.\n\n\n## Service Announcements\n\nAnnounce your service by submitting JSON over HTTP to etcd with information\nabout your service. This information will then be available for queries via DNS.\nWe use the directory `/skydns` to anchor all names.\n\nWhen providing information you will need to fill out (some of) the following\nvalues.\n\n* Path - The path of the key in etcd, e.g. if the domain you want to\n  register is \"rails.production.east.skydns.local\", you need to reverse it\n  and replace the dots with slashes. So the name here becomes:\n    `local/skydns/east/production/rails`.\n  Then prefix the `/skydns/` string too, so the final path becomes\n    `/v2/keys/skydns/local/skydns/east/production/rails`\n* Host - The name of your service, e.g., `service5.mydomain.com` or an IP address (either v4 or v6);\n* Port - the port where the service can be reached;\n* Priority - the priority of the service, the lower the value, the more preferred;\n* Weight - a weight factor that will be used for services with the same Priority;\n* Text - text you want to add (this returned when doing a TXT query);\n* TTL - the time-to-live of the service, overriding the default TTL. If the etcd\n  key also has a TTL, the minimum of this value and the etcd TTL is used.\n* TargetStrip - when synthesising a name for an IP only SRV record, take the path\n  name and strip `TargetStrip` labels from the ride hand side.\n* Group - limit recursion and only return services that share the Group's value.\n\nPath is the only mandatory field. The lookups into Etcd will be done with\na *lower* cased path name.\n\nAdding the service can thus be done with:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/production/rails \\\n        -d value='{\"host\":\"service5.example.com\",\"priority\":20}'\n\nOr with [`etcdctl`](https://github.com/coreos/etcdctl):\n\n    etcdctl set /skydns/local/skydns/east/production/rails \\\n        '{\"host\":\"service5.example.com\",\"priority\":20}'\n\nWhen doing a SRV query for these keys an SRV record is returned with the\npriority and a certain weight. The weight of a service is calculated as follows.\nWe treat weight as a percentage, so if there are\n3 services, the weight is set to 33 for each:\n\n| Service | Weight  | SRV.Weight |\n| --------| ------- | ---------- |\n|    a    |   100   |    33      |\n|    b    |   100   |    33      |\n|    c    |   100   |    33      |\n\nIf we add other weights to the equation some services will get a different\nWeight:\n\n| Service | Weight  | SRV.Weight |\n| --------| ------- | ---------- |\n|    a    |   120   |    34      |\n|    b    |   100   |    28      |\n|    c    |   130   |    37      |\n\nNote, all calculations are rounded down, so the sum total might be lower than\n100.\n\nWhen querying the DNS for services you can use wildcards or query for\nsubdomains. See the section named \"Wildcards\" below for more information.\n\n\n## Service Discovery via the DNS\n\nYou can find services by querying SkyDNS via any DNS client or utility. It uses\na known domain syntax with subdomains to find matching services.\n\nFor the purpose of this document, let's suppose we have added the following\nservices to etcd:\n\n* 1.rails.production.east.skydns.local, mapping to service1.example.com\n* 2.rails.production.west.skydns.local, mapping to service2.example.com\n* 4.rails.staging.east.skydns.local, mapping to 10.0.1.125\n* 6.rails.staging.east.skydns.local, mapping to 2003::8:1\n\nThese names can be added with:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/production/rails/1 \\\n        -d value='{\"host\":\"service1.example.com\",\"port\":8080}'\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/west/production/rails/2 \\\n        -d value='{\"host\":\"service2.example.com\",\"port\":8080}'\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/staging/rails/4 \\\n        -d value='{\"host\":\"10.0.1.125\",\"port\":8080}'\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/staging/rails/6 \\\n        -d value='{\"host\":\"2003::8:1\",\"port\":8080}'\n\nTesting one of the names with `dig`:\n\n    % dig @localhost SRV 1.rails.production.east.skydns.local\n\n    ;; ANSWER SECTION:\n    1.rails.production.east.skydns.local. 3600 IN SRV 10 0 8080 service1.example.com.\n\n\n### Wildcards\n\nOf course using the full names isn't *that* useful, so SkyDNS lets you query for\nsubdomains, and returns responses based upon the amount of services matched by\nthe subdomain or from the wildcard query.\n\nIf we are interested in all the servers in the `east` region, we simply omit the\nrightmost labels from our query:\n\n    % dig @localhost SRV east.skydns.local\n\n    ;; ANSWER SECTION:\n    east.skydns.local.      3600    IN      SRV     10 20 8080 service1.example.com.\n    east.skydns.local.      3600    IN      SRV     10 20 8080 4.rails.staging.east.skydns.local.\n    east.skydns.local.      3600    IN      SRV     10 20 8080 6.rails.staging.east.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    4.rails.staging.east.skydns.local. 3600 IN A    10.0.1.125\n    6.rails.staging.east.skydns.local. 3600 IN AAAA 2003::8:1\n\nHere all three entries of the `east` are returned.\n\nThere is one other feature at play here. The second and third names,\n`{4,6}.rails.staging.east.skydns.local`, only had an IP record configured. Here\nSkyDNS used the etcd path (also see `TargetStrip`) to\nconstruct a target name and then puts the actual IP address in the additional\nsection. Directly querying for the A records of\n`4.rails.staging.east.skydns.local.` of course also works:\n\n    % dig @localhost -p 5354 +noall +answer A 4.rails.staging.east.skydns.local.\n\n    4.rails.staging.east.skydns.local. 3600 IN A    10.0.1.125\n\nAnother way to leads to the same result it to query for `*.east.skydns.local`,\nyou even put the wildcard (the `*` or `any`) in the middle of a name\n`staging.*.skydns.local` or `staging.any.skydns.local` is a valid query, which\nreturns all name in staging, regardless of the region. Multiple wildcards per\nname are also permitted.\n\nNote that `any` is synonymous for a `*`, as shown above.\n\n\n### Examples\n\nNow we can try some of our example DNS lookups:\n\n\n#### SRV Records\n\nGet all Services in staging.east:\n\n    % dig @localhost staging.east.skydns.local. SRV\n\n    ;; ANSWER SECTION:\n    staging.east.skydns.local. 3600 IN  SRV 10 50 8080 4.rails.staging.east.skydns.local.\n    staging.east.skydns.local. 3600 IN  SRV 10 50 8080 6.rails.staging.east.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    4.rails.staging.east.skydns.local. 3600 IN A    10.0.1.125\n    6.rails.staging.east.skydns.local. 3600 IN AAAA 2003::8:1\n\nIf you ask for a service who's Host value is an IP address you would (in theory) get\nback a SRV record such as:\n\n    % dig @localhost 4.rails.staging.east.skydns.local SRV\n\n    ;; ANSWER SECTION:\n    4.rails.staging.east.skydns.local 3600 IN SRV 10 100 8080 10.0.1.125\n\nWhere the target of the SRV is an IP address. This is not how SRV records work.\nSkyDNS will in this case synthesize a domain name and add the actual IP\naddress to the additional section of the response:\n\n    % dig @localhost 4.rails.staging.east.skydns.local SRV\n\n    ;; ANSWER SECTION:\n    4.rails.staging.east.skydns.local 3600 IN SRV 10 100 4.rails.staging.east.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    4.rails.staging.east.skydns.local. 3600 IN A    10.0.1.125\n\nWhich conveys the same information and is legal in the DNS. To have some control on how\nthe target names look you can register a service with `TargetStrip` set to a non-zero\nvalue. Setting TargetStrip to \"2\" strips 2 labels from the generated target name:\n\n    ;; ANSWER SECTION:\n    4.rails.staging.east.skydns.local 3600 IN SRV 10 100 staging.east.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    staging.east.skydns.local. 3600 IN A    10.0.1.125\n\nWhich removed the `4.rails` from the target name.\n\n#### A/AAAA Records\nTo return A records, simply run a normal DNS query for a service matching the\nabove patterns.\n\nNow do a normal DNS query:\n\n    % dig @localhost staging.east.skydns.local. A\n\n    ;; ANSWER SECTION:\n    staging.east.skydns.local. 3600 IN  A   10.0.1.125\n\nNow you have a list of all known IP Addresses registered running in staging in\nthe east area.\n\nBecause we're returning A records and not SRV records, there are no ports\nlisted, so this is only useful when you're querying for services running on\nports known to you in advance.\n\n\n#### MX Records\n\nIf a service is added with `\"mail\": true` it is *also* an MX record, the Priority\ndoubles as the MX's Preference.\n\n\n#### CNAME Records\n\nIf for an A or AAAA query the IP address can not be parsed, SkyDNS will try to\nsee if there is a chain of names that will lead to an IP address. The chain can\nnot be longer than 8. So for instance if the following services have been\nregistered:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/production/rails/1 \\\n        -d value='{\"host\":\"service1.skydns.local\",\"port\":8080}'\n\nand\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/service1 \\\n        -d value='{\"host\":\"10.0.2.15\",\"port\":8080}'\n\nWe have created the following CNAME chain:\n`1.rails.production.east.skydns.local` -\u003e `service1.skydns.local` -\u003e\n`10.0.2.15`. If you then query for an A or AAAA for\n1.rails.production.east.skydns.local SkyDNS returns:\n\n    1.rails.production.east.skydns.local. 3600  IN  CNAME   service1.skydns.local.\n    service1.skydns.local.                 3600  IN  A       10.0.2.15\n\n\n##### External Names\n\nIf the CNAME chains leads to a name that falls outside of the domain (i.e. does\nnot end with `skydns.local.`), a.k.a. an external name, SkyDNS will attempt to\nresolve that name using the supplied nameservers. If this succeeds the reply is\nconcatenated to the current one and send to the client. So if we register this\nservice:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/east/production/rails/1 \\\n        -d value='{\"host\":\"www.miek.nl\",\"port\":8080}'\n\nDoing an A/AAAA query for this will lead to the following response:\n\n    1.rails.production.east.skydns.local. 3600 IN CNAME www.miek.nl.\n    www.miek.nl.            3600    IN      CNAME   a.miek.nl.\n    a.miek.nl.              3600    IN      A       176.58.119.54\n\nThe first CNAME is generated from within SkyDNS, the other CNAME is returned\nfrom the remote name server.\n\n\n#### TXT Records\n\nSkyDNS also allows you to query for TXT records. Just register a json with the\n'text' field set.\n\n\n#### NS Records\n\nFor DNS to work properly SkyDNS needs to tell its parents its nameservers. This\ninformation is stored inside etcd, under the key `local/skydns/dns/ns`. There\nmultiple services maybe stored. Note these services MUST use IP address, using\nnames will not work. For instance:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dns/ns/ns1 \\\n        -d value='{\"host\":\"172.16.0.1\"}'\n\nRegisters `ns1.ns.dns.skydns.local` as a nameserver with IP address 172.16.0.1:\n\n    % dig @localhost NS skydns.local\n\n    ;; ANSWER SECTION:\n    skydns.local.       3600    IN  NS  ns1.ns.dns.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    n1.ns.dns.skydns.local.    3600    IN  A   172.16.0.1\n\nHaving the nameserver(s) in etcd make sense because usually it is hard for\nSkyDNS to figure this out by itself, especially when running behind NAT or\nrunning on 127.0.0.1:53 and being forwarded packets IPv6 packets, etc. etc.\n\n\n#### PTR Records: Reverse Addresses\n\nWhen registering a service with an IP address only, you might also want to\nregister the reverse (adding a hostname the address points to). In the DNS these\nrecords are called PTR records.\n\nSo looking back at some of the services in the section \"Service Discovery via\nthe DNS\", we register these IP only ones:\n\n    4.rails.staging.east.skydns.local. 10.0.1.125\n\nTo add the reverse of this address you need to add the DNS name that will be used\nwhen doing a reverse lookup. With `dig -x \u003cIP address\u003e` you can easiliy find\nwhat the reverse name should be:\n\n    % dig -x 10.0.1.125 +noall +question\n    ;125.1.0.10.in-addr.arpa.   IN  PTR\n\nSo the name must be `125.1.0.10.in-addr.arpa` which should point to\n`4.rails.staging.east.skydns.local`.\n\nThese can be added with the following command. Note that the IP address is\nreversed *again* and is actually back in its original form.\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/arpa/in-addr/10/0/1/125 \\\n        -d value='{\"host\":\"4.rails.staging.east.skydns.local\"}'\n\nIf SkyDNS receives a PTR query it will check these paths and will return the\ncontents. Note that these replies are sent with the AA (Authoritative Answer)\nbit *off*. If nothing is found locally the query is forwarded to the local\nrecursor (if so configured), otherwise SERVFAIL is returned.\n\nThis also works for IPv6 addresses, except that the reverse path is quite long.\n\n\n#### DNS Forwarding\n\nBy specifying nameservers in SkyDNS's config, for instance\n`8.8.8.8:53,8.8.4.4:53`, you create a DNS forwarding proxy. In this case it\nround-robins between the two nameserver IPs mentioned.\n\nRequests for which SkyDNS isn't authoritative will be forwarded and proxied back\nto the client. This means that you can set SkyDNS as the primary DNS server in\n`/etc/resolv.conf` and use it for both service discovery and normal DNS\noperations.\n\n\n#### DNSSEC\n\nSkyDNS supports signing DNS answers, also known as DNSSEC. To use it, you need\nto create a DNSSEC keypair and use that in SkyDNS. For instance, if the domain\nfor SkyDNS is `skydns.local`:\n\n    % dnssec-keygen skydns.local\n    Generating key pair............++++++ ...................................++++++\n    Kskydns.local.+005+49860\n\nThis creates two files with the basename `Kskydns.local.+005.49860`, one with\nthe extension `.key` (this holds the public key) and one with the extension\n`.private` which holds the private key. The basename of these files should be\ngiven to SkyDNS's DNSSEC configuration option like so (together with some other\noptions):\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/config -d \\\n        value='{\"dns_addr\":\"127.0.0.1:5354\",\"dnssec\":\"Kskydns.local.+005+55656\"}'\n\nIf you then query with `dig +dnssec` you will get signatures, keys and NSEC3\nrecords returned. Authenticated denial of existence is implemented using NSEC3\nwhite lies, see [RFC7129](http://tools.ietf.org/html/rfc7129), Appendix B.\n\n\n#### Host Local Values\n\nSkyDNS supports storing values which are specific for that *instance* of SkyDNS.\n\nThis can be useful when you have SkyDNS running on multiple hosts, but want to\nstore values that are specific for a single host. For example the public\nIP-address of the host or the IP-address on the tenant network.\n\nTo do that you need to specify a unique value for that host with `-local`.\nA good unique value for that would be an UUID which you can generate with\n`uuidgen` for instance.\n\nThat unique value is used as a path in etcd to store the values separately from\nthe normal values. It is still stored in the etcd backend so a restart of SkyDNS\nwith the same unique value will give it access to the old data.\n\nIn the example here, we don't use an UUID, we use `public.addresses`:\n\n    % skydns -local public.addresses.skydns.local \u0026\n\n    % curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/local/addresses/public \\\n        -d value='{\"host\":\"192.0.2.1\"}'\n\n    % dig @127.0.0.1 local.dns.skydns.local. A\n\n    ;; ANSWER SECTION:\n    local.dns.skydns.local. 3600 IN  A   192.0.2.1\n\nThe name `local.dns.skydns.local.` is fixed, i.e. you can retrieve the Host\nLocal Value by querying for `local.dns.\u003cyour domain\u003e`.\n\n\n#### Groups\n\nGroups can be used to group set of services together. The main use of this is to\nlimit recursion, i.e. don't give back *all* records, but only a subset. Say that\nI have configuration like this:\n\n    /skydns/local/domain/\n    /skydns/local/domain/a - {\"host\": \"127.0.0.1\", \"group\": \"g1\"}\n    /skydns/local/domain/b - {\"host\": \"127.0.0.2\", \"group\": \"g1\"}\n    /skydns/local/domain/subdom/\n    /skydns/local/domain/subdom/c - {\"host\": \"127.0.0.3\", \"group\": \"g2\"}\n    /skydns/local/domain/subdom/d - {\"host\": \"127.0.0.4\", \"group\": \"g2\"}\n\nAnd you want `domain.local` to return (127.0.0.1 and 127.0.0.2) and\n`subdom.domain.local` to return (127.0.0.3 and 127.0.0.4). For this the two\ndomains, need to be in different groups. What those groups are does not matter,\nas long as `a` and `b` belong to the same group which is *different* from the\ngroup `c` and `d` belong to. If a service is found *without* a group it is\n*always included*.\n\n\n## Implementing a custom DNS backend\n\nThe SkyDNS `server` package may be used as a library, which allows a custom\nrecord retrieval implementation (referred to as a `Backend`) to be provided. The\ndefault Etcd implementation resides under `backends/etcd/etcd.go`. To provide\nyour own backend implementation, you must implement the `server.Backend`\ninterface.\n\nIf you want to preserve the ability to answer arbitrary queries from etcd, but use\nyour custom implementation for certain subsets of the namespace, the\n`server.FirstBackend` helper type will allow you to chain multiple `Backends` in\norder. The first backend that answers a `Records` or `ReverseRecord` call with\na record and with no error will be served.\n\n\n## Stub Zones\n\nStub Zones are pointers that point to *another set* of servers which should\nprovide an answer for the current query. This is similar to the (recursive)\nforwarding SkyDNS does, but different in that you need to specify a domain name\nand a set of authoritative servers. Also this can be dynamically controlled by\nwriting values into Etcd. Note, that when enabled SkyDNS will *first* consult\nthe stub configuration, potentially bypassing any configured local records.\n\nThe stub zone configuration lives under `stub.dns.skydns.local.`. The following\nexample shows on how to set this up. Suppose we want to create a stub zone for\n`skydns.com` and point to the nameservers reachable by following address *and*\n(optional) ports:\n\n* 172.16.1.1, port 54\n* 10.10.244.1, port 53 (53 is the default that will be used if there isn't one\n    specified)\n\nWe should then register 2 services under the name `skydns.com.stub.dns.skydns.local`\n\n    % curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dns/stub/com/skydns/ns1 \\\n        -d value='{\"host\":\"172.16.1.1\", \"port\":54}'\n    % curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dns/stub/com/skydns/ns2 \\\n        -d value='{\"host\":\"10.10.244.1\"}'\n\nSo the *leaves* should have the nameserver information.\n\n    xxx.\u003cdomain name\u003e.stub.dns.skydns.local\n    |           |\n    v           |\n    nameservers |\n                v\n          stub domain name\n\nWhen SkyDNS receives a query for `skydns.com` it will *not* forward it to the\nrecursors, but instead will query 172.16.1.1 on port 54 and if that fails will\nquery 10.10.244.1 (on 53) to get an answer. That answer will then be given back\nto the original client.\n\nWhen forwarding to a stub, SkyDNS adds a EDNS0 meta data RR to the packet\ntelling the remote server (if its a SkyDNS instance) that this is a stub request.\nSkyDNS will not (stub)forward packets with this EDNS0 meta data, instead the request\nwill be dropped and logged.\n\nRemember this will only work when SkyDNS is started with `-stubzones`.\n\n\n## How Do I Create an Address Pool and Round Robin Between Them\n\nYou have 3 machines with 3 different IP addresses and you want to have\n1 name pointing to all 3 possible addresses. The name we want to use is:\n  `db.skydns.local` and the 3 addresses are 127.0.0.{1,2,3}. For this to work we\n  create the hosts named `x{1,2,3}.db.skydns.local` in etcd:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/db/x1 -d \\\n        value='{\"host\":\"127.0.0.1\"}'\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/db/x2 -d \\\n        value='{\"host\": \"127.0.0.2\"'}\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/db/x3 -d \\\n        value='{\"host\": \"127.0.0.3\"'}\n\nNow the name `db.skydns.local` is the \"load balanced\" name for the database, SkyDNS\nwill round-robin by default in this case unless `-round-robin=false` is enabled.\n\n\n## How I Do Create Multiple SRV Records For the Same Name\n\nYou want this response from SkyDNS, which says there are 2 open\nports on bar.skydns.local and this name has IP addres 192.168.0.1:\n\n    ;; ANSWER SECTION:\n    bar.skydns.local.   3600    IN  SRV 10 50 80 bar.skydns.local.\n    bar.skydns.local.   3600    IN  SRV 10 50 443 bar.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    bar.skydns.local. 3600    IN  A   192.168.0.1\n\nSo you register a \"dummy\" host named `x1`:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/bar/x1 -d \\\n        value='{\"host\":\"192.168.0.1\",\"port\":80}'\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/bar/x2 -d \\\n        value='{\"host\": \"bar.skydns.local\",\"port\":443}'\n\nAnd try it out:\n\n    ;; ANSWER SECTION:\n    bar.skydns.local.   3600    IN  SRV 10 50 80 x1.bar.skydns.local.\n    bar.skydns.local.   3600    IN  SRV 10 50 443 bar.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    x1.bar.skydns.local. 3600    IN  A   192.168.0.1\n\nWhich has `x1` in the name, which is not the name you wanted to see there, and\nworse does not match the name in the other SRV record. To makes this work you'll\nneed `TargetStrip` which allows you to tell SkyDNS to strip labels from the name\nit makes up:\n\n    curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/bar/x1 -d \\\n        value='{\"host\":\"192.168.0.1\",\"port\":80,\"targetstrip\":1}'\n\n    % dig @127.0.0.1 bar.skydns.local. SRV\n\n    ;; ANSWER SECTION:\n    bar.skydns.local.   3600    IN  SRV 10 50 80 bar.skydns.local.\n    bar.skydns.local.   3600    IN  SRV 10 50 443 bar.skydns.local.\n\n    ;; ADDITIONAL SECTION:\n    bar.skydns.local. 3600    IN  A   192.168.0.1\n\n\n## How do you limit recursion?\n\nBy default SkyDNS will returns *all* records under a name. Suppose you want we have\n`bar.skydns.local`... TODO.\n\n\n# Docker\n\nOfficial Docker images are at the [Docker Hub](https://registry.hub.docker.com/u/skynetservices/skydns/):\n\n* master -\u003e skynetservices/skydns:latest\n* latest tag -\u003e skynetservices/skydns:latest-tagged\n\nThe supplied `Dockerfile` can be used to build an image as well. Note that the image\nis based of Alpine Linux which used musl libc instead of glibc, so when building\nSkyDNS you must make sure if does not need glibc when run:\n\nBuild SkyDNS with:\n\n    % GOOS=linux go build -a -tags netgo -installsuffix netgo\n\nAnd then build the docker image:\n\n    % docker build -t $USER/skydns .\n\nIf you run it, SkyDNS needs to access Etcd (or whatever backend), which usually\nruns on the host server (i.e. when using CoreOS), to make that work, just run:\n\n    docker run --net host \u003cimage\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskynetservices%2Fskydns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskynetservices%2Fskydns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskynetservices%2Fskydns/lists"}