coredns is a free, open source networking & connectivity project written in Go and released under Apache-2.0. It has 14,329 GitHub stars, 2,532 forks and 282 open issues, and was last pushed yesterday. On this registry it ranks #10 of 14 tracked projects in Networking & Connectivity, with 5 head-to-head comparisons available.

What is coredns?

CoreDNS is a CNCF-graduated DNS server and forwarder written in Go that resolves queries through a chain of plugins, aimed at platform and infrastructure engineers who run DNS for Kubernetes clusters, service discovery, or authoritative zones and need to extend its behaviour without forking the core.

What it is

CoreDNS is a DNS server and forwarder, written in Go, that chains plugins. Each plugin performs a distinct DNS function, and the request travels a defined path through the chain, so the behaviour of the server is the sum of the plugins configured for the zone rather than the product of a hard-coded resolver. It is licensed under Apache-2.0 and is a Cloud Native Computing Foundation graduated project, with first-party plugins documented at coredns.io/plugins and community plugins at coredns.io/explugins.

The concrete problem it solves is the coupling between DNS answers and the system that owns the truth about them. CoreDNS serves zone data from files on disk with the file and auto plugins, retrieves zone data from primaries as a secondary server with the secondary plugin, uses Kubernetes as a backend with the kubernetes plugin, and uses etcd as a backend with the etcd plugin, which replaces SkyDNS in that role. Where an operator needs behaviour that does not ship out of the box, it can be added by writing a plugin rather than maintaining a patch against the resolver.

Key capabilities

  • Serves DNS over UDP and TCP, TLS (DoT, RFC 7858), DNS over HTTP/2 (DoH, RFC 8484), DNS over HTTP/3 (DoH3), DNS over QUIC (DoQ, RFC 9250), and gRPC.
  • Backends for zone data and discovery: kubernetes for Kubernetes service discovery, etcd replacing SkyDNS, file and auto for zone files loaded from disk, and route53 for cloud provider integration.
  • Authoritative and secondary operation: file with transfer allows zone transfers as a primary, while secondary pulls zone data from primaries over AXFR, and dnssec signs zone data on the fly.
  • Query processing plugins including cache for response caching, loadbalance for response load balancing, rewrite and template for rewriting qtype, qclass, and qname, any to block ANY queries, and dns64 for IPv6 translation.
  • Operational visibility through prometheus metrics, log query logging, errors error logging, and pprof profiling.
  • Protocol and compatibility details including the CH class with version.bind and friends via chaos, and the RFC 5001 name server identifier option via nsid.

Who uses it and how

  • Kubernetes operators use the kubernetes plugin as a cluster backend, making the cluster API the source of service-discovery records instead of a separately maintained zone file.
  • Teams running etcd-based service discovery use the etcd plugin as a direct replacement for SkyDNS, keeping the existing data store while changing the resolver.
  • Environments that require encrypted transport deploy it for DoT, DoH, DoH3, or DoQ listeners at the edge or in front of clients that mandate those protocols.
  • Zone operators run it as a primary with file and transfer, or as a secondary with secondary, alongside cloud-integrated records through route53.
  • SRE and platform teams enable prometheus, log, errors, and pprof when they need metrics, query traces, and profiling from the same process that answers DNS.
  • Organisations with requirements the in-tree plugins do not cover build out-of-tree plugins, and can enable them at compile time rather than maintaining a downstream fork.

Getting started

Build from source by cloning the repository and running make, which requires Go 1.26.0 or higher and yields a coredns binary; extra plugins can be compiled in by setting the COREDNS_PLUGINS environment variable to a comma-separated list in the same format as plugin.cfg. A Docker image is also published as coredns/coredns on Docker Hub for those who prefer not to set up a Go environment.

How it compares

Among the tools named in the facts, SkyDNS is the closest point of reference, and CoreDNS occupies the same service-discovery role through the etcd plugin that explicitly replaces it. The difference is architectural: SkyDNS answered from etcd as its purpose, while CoreDNS reaches the same data through one plugin in a chain that can also serve zone files, proxy to a recursive nameserver with forward, and listen on DoT, DoH, DoH3, and DoQ.

When to use it — and when not to

A self-hoster must operate the plugin chain configuration and whatever data source the chosen plugins depend on, such as a Kubernetes API, an etcd cluster, or zone files kept in step with the primary. It is a poor fit for anyone who wants a fully managed DNS service with no process to run, or who cannot build with Go 1.26.0 or higher and does not want to use the published container image. Known limits in the documented plugin set are worth weighing: secondary supports AXFR only, and DNSSEC support in the file plugin is NSEC only, so teams needing NSEC3 or IXFR should check current plugin documentation before committing.

project readme (upstream, from github) — read inline

CoreDNS

Documentation CodeQL Go Tests CircleCI Docker Pulls Go Report Card CII Best Practices OpenSSF Scorecard

CoreDNS is a DNS server/forwarder, written in Go, that chains plugins. Each plugin performs a (DNS) function.

CoreDNS is a Cloud Native Computing Foundation graduated project.

CoreDNS is a fast and flexible DNS server. The key word here is flexible: with CoreDNS you are able to do what you want with your DNS data by utilizing plugins. If some functionality is not provided out of the box you can add it by writing a plugin.

CoreDNS can listen for DNS requests coming in over:

  • UDP/TCP (go'old DNS).
  • TLS - DoT (RFC 7858).
  • DNS over HTTP/2 - DoH (RFC 8484).
  • DNS over HTTP/3 - DoH3
  • DNS over QUIC - DoQ (RFC 9250).
  • gRPC (not a standard).

Currently CoreDNS is able to:

  • Serve zone data from a file; both DNSSEC (NSEC only) and DNS are supported (file and auto).
  • Retrieve zone data from primaries, i.e., act as a secondary server (AXFR only) (secondary).
  • Sign zone data on-the-fly (dnssec).
  • Load balancing of responses (loadbalance).
  • Allow for zone transfers, i.e., act as a primary server (file + transfer).
  • Automatically load zone files from disk (auto).
  • Caching of DNS responses (cache).
  • Use etcd as a backend (replacing SkyDNS) (etcd).
  • Use k8s (kubernetes) as a backend (kubernetes).
  • Serve as a proxy to forward queries to some other (recursive) nameserver (forward).
  • Provide metrics (by using Prometheus) (prometheus).
  • Provide query (log) and error (errors) logging.
  • Integrate with cloud providers (route53).
  • Support the CH class: version.bind and friends (chaos).
  • Support the RFC 5001 DNS name server identifier (NSID) option (nsid).
  • Profiling support (pprof).
  • Rewrite queries (qtype, qclass and qname) (rewrite and template).
  • Block ANY queries (any).
  • Provide DNS64 IPv6 Translation (dns64).

And more. Each of the plugins is documented. See coredns.io/plugins for all in-tree plugins, and coredns.io/explugins for all out-of-tree plugins.

Compilation from Source

To compile CoreDNS, we assume you have a working Go setup. See various tutorials if you don’t have that already configured.

First, make sure your golang version is 1.26.0 or higher as go mod support and other api is needed. See here for go mod details. Then, check out the project and run make to compile the binary:

$ git clone https://github.com/coredns/coredns
$ cd coredns
$ make

NOTE: extra plugins may be enabled when building by setting the COREDNS_PLUGINS environment variable with comma separate list of plugins in the same format as plugin.cfg

This should yield a coredns binary.

Compilation with Docker

CoreDNS requires Go to compile. However, if you already have docker installed and prefer not to setup a Go environment, you could build CoreDNS easily:

docker run --rm -i -t \
    -v $PWD:/go/src/github.com/coredns/coredns -w /go/src/github.com/coredns/coredns \
        golang:1.25 sh -c 'GOFLAGS="-buildvcs=false" make gen && GOFLAGS="-buildvcs=false" make'

The above command alone will have coredns binary generated.

Quick Start

Create a minimal Corefile:

cat > Corefile <<EOF
.:53 {
    forward . 8.8.8.8
    log
}
EOF

Run CoreDNS:

$ ./coredns -conf Corefile

Test it:

$ dig @127.0.0.1 google.com

Examples

JSON Logging

Start CoreDNS with -log-format=json to emit operational logs as single-line JSON. The default -log-format=text retains the existing text output. The format applies to the whole process, including all server blocks, and persists across Corefile reloads. Query logging still requires the log plugin.

./coredns -conf Corefile -log-format=json

Records contain time (RFC3339 with fractional seconds), level (DEBUG, INFO, WARN, ERROR, or FATAL), and msg. Named plugin loggers also include plugin. Messages, including embedded newlines and DNS escapes, are JSON-encoded rather than concatenated into JSON templates. Debug output still requires debug. See the log plugin for typed query fields.

The standard library's default logger (including Caddy's lifecycle messages) is routed through the same backend at INFO level; its original message is retained without guessing severity or fields from text. Independently configured third-party loggers, direct stdout/stderr writes, and Go runtime diagnostics are not intercepted. Command-line help, flag parsing errors, -version, and -plugins remain human-readable. Normal startup, Corefile errors, and query/error plugin logs use the selected format.

Querying CoreDNS

When starting CoreDNS without any configuration, it loads the whoami and log plugins and starts listening on port 53 (override with -dns.port), it should show the following:

.:53
CoreDNS-1.6.6
linux/amd64, go1.16.10, aa8c32

The following could be used to query the CoreDNS server that is running now:

dig @127.0.0.1 -p 53 www.example.com

Any query sent to port 53 should return some information; your sending address, port and protocol used. The query should also be logged to standard output.

The configuration of CoreDNS is done through a file named Corefile. When CoreDNS starts, it will look for the Corefile from the current working directory. A Corefile for CoreDNS server that listens on port 53 and enables whoami plugin is:

.:53 {
    whoami
}

Sometimes port number 53 is occupied by system processes. In that case you can start the CoreDNS server while modifying the Corefile as given below so that the CoreDNS server starts on port 1053.

.:1053 {
    whoami
}

If you have a Corefile without a port number specified it will, by default, use port 53, but you can override the port with the -dns.port flag: coredns -dns.port 1053, runs the server on port 1053.

You may import other text files into the Corefile using the import directive. You can use globs to match multiple files with a single import directive.

.:53 {
    import example1.txt
}
import example2.txt

You can use environment variables in the Corefile with {$VARIABLE}. Note that each environment variable is inserted into the Corefile as a single token. For example, an environment variable with a space in it will be treated as a single token, not as two separate tokens.

.:53 {
    {$ENV_VAR}
}

A Corefile for a CoreDNS server that forward any queries to an upstream DNS (e.g., 8.8.8.8) is as follows:

.:53 {
    forward . 8.8.8.8:53
    log
}

Start CoreDNS and then query on that port (53). The query should be forwarded to 8.8.8.8 and the response will be returned. Each query should also show up in the log which is printed on standard output.

To serve the (NSEC) DNSSEC-signed example.org on port 1053, with errors and logging sent to standard output. Allow zone transfers to everybody, but specifically mention 1 IP address so that CoreDNS can send notifies to it.

example.org:1053 {
    file /var/lib/coredns/example.org.signed
    transfer {
        to * 2001:500:8f::53
    }
    errors
    log
}

Serve example.org on port 1053, but forward everything that does not match example.org to a recursive nameserver and rewrite ANY queries to HINFO.

example.org:1053 {
    file /var/lib/coredns/example.org.signed
    transfer {
        to * 2001:500:8f::53
    }
    errors
    log
}

. {
    any
    forward . 8.8.8.8:53
    errors
    log
}

readme truncated — read the full docs on github

Frequently asked questions

Is coredns free to use?

coredns is open source under the Apache-2.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does coredns do?

CoreDNS is a DNS server that chains plugins

What is coredns written in?

coredns is primarily written in Go. Its source is publicly available at https://github.com/coredns/coredns, and it has 14,329 GitHub stars.