CoreDNS on AWS User Guide
Overview
This guide covers the deployment and configuration of CoreDNS on AWS using cloudimg AWS Marketplace images. CoreDNS is a fast, flexible, plugin based DNS server and a CNCF graduated project, best known as the default DNS server for Kubernetes. It is a single self contained Go binary whose entire behaviour is defined by a plain text Corefile, so you compose exactly the DNS pipeline you need from a chain of plugins rather than wiring together several daemons.
The image installs CoreDNS 1.14.6 from the official prebuilt release tarball, run under systemd as an unprivileged coredns user with just the CAP_NET_BIND_SERVICE capability so it can bind the standard privileged DNS port. CoreDNS answers DNS on port 53 over both UDP and TCP, publishes Prometheus metrics on port 9153, and exposes a loopback health endpoint on port 8080. There is no web interface and no database: the Corefile (/etc/coredns/Corefile) plus a zone file are the whole configuration.
Secure by default — not an open resolver. A naively deployed public resolver can be abused for DNS amplification attacks. This image avoids that: the shipped Corefile has two server blocks. An authoritative block serves the demonstration zone cloudimg.internal with the authoritative answer flag on all interfaces, and a recursive cache and forward block whose acl plugin allows recursion only from the local host and answers every other source with REFUSED. On the first boot of every instance the instance IP is baked into the demo zone so DNS answers immediately. CoreDNS has no login, so no shared or default credential of any kind ships in the image.
What is included:
-
CoreDNS 1.14.6 from the official prebuilt release binary, run under systemd as the unprivileged
corednsuser (coredns.service) -
A DNS endpoint on
0.0.0.0:53(UDP and TCP), a Prometheus metrics endpoint on:9153, and a health endpoint on:8080 -
An authoritative demonstration zone
cloudimg.internal, served with the AA flag on all interfaces, whose records point at this instance's IP (baked in on first boot via EC2 instance metadata) -
A recursive cache and forward resolver restricted by the
aclplugin to loopback only, so the image is not an open resolver until you deliberately open it to your trusted subnets -
The whole configuration in one readable file,
/etc/coredns/Corefile, that you version control and reload with a single command -
The systemd-resolved stub listener disabled so CoreDNS owns port 53 cleanly, while the OS keeps resolving names through the upstream resolver list
Connecting to your instance
Connect over SSH on port 22 as the default login user for the AMI variant you launched. CoreDNS has no login or password of its own, so nothing secret ships in the image.
| OS variant | SSH login user | Notes |
|---|---|---|
| Ubuntu 24.04 LTS | ubuntu |
coredns.service; config at /etc/coredns/Corefile |
ssh -i /path/to/key.pem ubuntu@<public-ip>
Prerequisites
-
An AWS account and a key pair in the target region
-
Subscription to the CoreDNS listing on AWS Marketplace
-
A security group allowing TCP 22 (admin) from your address, UDP 53 and TCP 53 (DNS) from the clients that will query the server, and optionally TCP 9153 from your monitoring network for metrics
Recommended instance type: m5.large (2 vCPU, 8 GB RAM) is ample for a small authoritative server or a departmental resolver. CoreDNS is extremely light; larger sizes are only needed for very high query volumes.
Step 1: Launch from AWS Marketplace
Search CoreDNS in AWS Marketplace, select the cloudimg listing, and click Continue to Subscribe, then Continue to Configuration and Continue to Launch. Choose the m5.large instance type, your key pair, and a security group. Configure the security group to allow UDP 53 and TCP 53 from the clients that will query the server, and TCP 22 for administration. If you host public authoritative zones, 53 must be reachable from the internet; if you run a recursive resolver for your own networks, keep 53 restricted to your internal subnets.
Step 2: Launch from the AWS CLI
AWS_REGION="us-east-1"
aws ec2 run-instances \
--region "$AWS_REGION" \
--image-id <coredns-ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <your-sg-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=coredns1}]'
Open UDP 53, TCP 53 and TCP 22 in <your-sg-id> scoped to the sources that need them.
Step 3: First boot
On first boot the image resolves this instance's IP through EC2 instance metadata (IMDSv2), renders the demonstration zone /etc/coredns/zones/db.cloudimg.internal from the shipped template (baking the IP into the demo, www and ns1 records and setting a fresh SOA serial), writes the informational note /root/coredns-aws-info.txt, and starts coredns. This completes within seconds. SSH in as ubuntu and read the note:
sudo cat /root/coredns-aws-info.txt
The note records the demo zone name, the demo record, this instance's IP, the metrics URL, and the paths to the Corefile and zone file. CoreDNS has no password, so the note holds no secret.
Step 4: Confirm the service is running
coredns.service is active, coredns -version reports 1.14.6, and ss confirms it is listening on :53 for DNS (UDP and TCP), :9153 for metrics and :8080 for health.
systemctl is-active coredns.service
/opt/coredns/coredns -version
sudo ss -tulnp | grep -E ':53 |:9153 |:8080 '

Step 5: Query the authoritative demo zone
The demonstration zone cloudimg.internal is served authoritatively. Query its SOA and the demo A record on the loopback address. The answer carries the aa (authoritative answer) flag, and demo.cloudimg.internal resolves to this instance's IP. DNS over TCP works too, which is what zone transfers and large responses use.
dig +noall +answer @127.0.0.1 SOA cloudimg.internal
dig @127.0.0.1 A demo.cloudimg.internal
dig +tcp +short @127.0.0.1 A www.cloudimg.internal
In the second command, look for flags: qr aa rd in the header — the aa flag confirms CoreDNS is answering authoritatively for this zone rather than recursing.

Step 6: Prometheus metrics and health
CoreDNS exposes a Prometheus metrics endpoint on port 9153 (every server, plugin and response code is a labelled series) and a plain health endpoint on port 8080 that returns OK while the server is up. Point your Prometheus scraper at :9153 and your load balancer or uptime monitor at :8080/health.
curl -s http://127.0.0.1:9153/metrics | grep '^coredns_' | head
curl -s http://127.0.0.1:8080/health; echo

Step 7: Confirm the image is not an open resolver
This is the security posture that matters for a public DNS server. The default .:53 block forwards and caches recursive queries, but its acl plugin allows recursion only from loopback and answers every other source with REFUSED. Read the acl block, then send a recursive query from this instance's own non loopback address and confirm it is refused.
sudo grep -A3 'acl {' /etc/coredns/Corefile
IP=$(hostname -I | awk '{print $1}')
dig @"$IP" A probe.invalid | grep -E 'status:'
The recursive query from the non loopback source returns status: REFUSED, proving the image cannot be abused for DNS amplification out of the box. Authoritative answers for cloudimg.internal are still served to everyone (Step 5) — only recursion is restricted.

Step 8: Serve your own authoritative zone
You add authoritative zones by dropping a zone file into /etc/coredns/zones and adding a matching server block to the Corefile. The example below uses <your-domain> as a placeholder for a domain you own. Create the zone file, add the block, and reload.
# 1) create a zone file for <your-domain> in /etc/coredns/zones/db.<your-domain>
# (use the shipped db.cloudimg.internal.template as a starting point)
# 2) add a server block to /etc/coredns/Corefile:
# <your-domain>:53 {
# file /etc/coredns/zones/db.<your-domain>
# log
# errors
# }
# 3) apply the change:
sudo systemctl reload coredns
CoreDNS validates the Corefile on reload; if there is a syntax error it keeps serving the previous configuration. To publish the zone on the internet, point your registrar's NS records at this instance's public IP.
Step 9: Open recursion to your trusted networks
To let your own clients use the instance as a recursive resolver, add their subnets to the acl allow net line in the default .:53 block, then restart. Keep the list to networks you control — never open recursion to the whole internet.
# edit /etc/coredns/Corefile and extend the acl allow line in the .:53 block, e.g.
# allow net 127.0.0.0/8 ::1/128 10.0.0.0/8 192.168.0.0/16
sudo systemctl restart coredns
The upstreams used for forwarding are Quad9 (9.9.9.9) and its secondary (149.112.112.112); change the forward line in the Corefile if you prefer different resolvers or want DNS over TLS upstreams.
Step 10: Review the configuration and info note
Everything CoreDNS does is in the Corefile, and the per instance details are in the info note. Both are readable with sudo.
sudo cat /etc/coredns/Corefile
sudo cat /root/coredns-aws-info.txt
The info note is 0600 root:root and holds no secret — CoreDNS has no login. It simply records the demo zone, this instance's IP and the metrics URL for convenience.
Step 11: Security recommendations
-
Restrict the security group to your use case. For an internal recursive resolver, allow UDP 53 and TCP 53 only from your client subnets. For public authoritative zones, 53 must be internet reachable, but keep recursion loopback only (or scoped by the acl) so the server is never an open resolver.
-
Keep the acl tight. Only add subnets you control to the
allow netline. An overly broad allow list turns the server back into an open resolver. -
Restrict the metrics port. Port 9153 exposes query statistics. Open TCP 9153 only to your monitoring network, not the public internet.
-
Enable DNSSEC or DNS over TLS as needed. CoreDNS ships the
dnssec,tlsand forwardtls://plugins; enable them in the Corefile for signed zones and encrypted upstreams. -
Keep the OS patched. Unattended security upgrades remain enabled on the running instance.
Step 12: Support and Licensing
CoreDNS is an open source project distributed under the Apache License 2.0. This cloudimg image bundles the unmodified official CoreDNS release binary. cloudimg provides the packaging, the systemd hardening, the secure by default Corefile and acl posture, the per instance demo zone automation, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA.
cloudimg is not affiliated with or endorsed by the CoreDNS project or the CNCF. CoreDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on AWS
Find CoreDNS on the AWS Marketplace, published by cloudimg. Launch from the AWS console or the AWS CLI as shown above.
Need Help?
Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.