What is DNS? A server owner's guide
DNS decides whether your domain reaches your VPS. Learn the records, nameservers, TTL and the caching that makes a DNS change look like it failed.
What is DNS, and why your domain does not reach your VPS yet
DNS (domain name system) turns a name like example.com into an IP (internet protocol) address like 203.0.113.10. A browser cannot connect to a name. It connects to an address, so every page load starts with a DNS question and an answer. If you have just bought a domain and a VPS of your own, and nothing loads, one of two things is true: no record yet connects the name to your server's address, or a record does and something in the path is still handing out an older answer.
Both situations are normal, and neither means anything is broken. The sections below take the parts in the order you will meet them, starting with the one that wastes the most time: which control panel actually holds your records.
Every check here uses dig, which is not installed by default on a fresh Ubuntu or Debian machine.
sudo apt update && sudo apt install -y bind9-dnsutilsRegistrar, nameservers, DNS host: which one do you edit
These three names describe different jobs. Mixing them up is the most common reason an edit changes nothing.
- The registrar is the company you bought the domain from. Its critical job is delegation: it tells the registry that runs your TLD (top-level domain, the
.compart) which nameservers are authoritative for your domain. - The authoritative nameservers hold the real records for your zone. A zone is your domain and the names under it.
- The DNS host is whoever operates those nameservers. It can be the registrar, a separate provider, or
bind9running on a server you own.
You buy at the registrar. You edit at the DNS host. If you moved your domain to another provider's nameservers, the registrar's own DNS panel still shows you a zone, still saves your edits, and nobody on the internet ever asks that zone a question. The records are real. They are simply never consulted.
Find out where the world is asking:
dig example.com NS +short
dig +trace example.comThe first prints the nameservers answering for the domain today. The second walks the chain starting at the root servers and prints the referral the TLD servers hand out, which is the delegation your registrar controls. If those names belong to a provider you do not recognise, that provider owns the panel you need.
How a single lookup travels
Four parties are involved, and each one keeps a copy of what it learns.
- The stub resolver on your machine. It does no searching. It asks one configured server and believes the reply. On Ubuntu,
/etc/resolv.confis usually a symlink to/run/systemd/resolve/stub-resolv.confand names127.0.0.53, which issystemd-resolvedrunning locally with its own cache. - The recursive resolver. This is the resolver run by your ISP (internet service provider), or a public one such as
1.1.1.1, or one you run yourself. It does the actual work of finding the answer. - The root and TLD servers. The recursive resolver asks a root server, which does not know your address but replies with a referral to the
.comservers. Those reply with a referral to your nameservers. - The authoritative nameserver. It asks nobody. It answers from your zone and marks the answer authoritative.
dig +trace example.com shows you this happening, because it starts at the root itself and prints each referral instead of asking a cache. That is the fastest way to see whether the delegation and the zone agree.
The DNS records that matter when you run a server
A: a name to an IPv4 address.example.com. A 203.0.113.10. This is the record that points your domain at your VPS.AAAA: a name to an IPv6 address, such as2001:db8::10. Publish it only when your service really listens on that address. Clients on IPv6 networks try the AAAA answer first, so an address nothing answers on adds a stall to every visit.CNAME: an alias from one name to another name.www.example.com. CNAME example.com.sends visitors ofwwwto whatever the bare domain resolves to. A CNAME cannot live at the apex (the bareexample.com), because the apex must carry its own SOA (start of authority) and NS records, and a CNAME is not allowed to share a name with any other record. Providers offer workarounds under names like ALIAS, ANAME or CNAME flattening.MX: where mail for the domain is delivered. It carries a hostname and a preference number, and the lower number is tried first. An MX must point at a name that has an address record. Pointing one at a CNAME is invalid, and some sending servers will reject it.TXT: free text, used for proof and policy. Mail authentication records (SPF, DKIM, DMARC) live here, as does the ACME (automatic certificate management environment) token that issues a wildcard certificate.NS: which nameservers serve the zone. The copy that decides where the world asks lives in the parent zone and comes from your registrar's delegation, not the copy inside your own zone.
Two details cause more confusion than the record types themselves. A name ending in a dot is absolute, so www.example.com. means exactly that and nothing more. Most panels expect a relative name and append the domain for you, so typing www.example.com into the name box gives you www.example.com.example.com, which resolves for nobody. The other detail is @, which in almost every panel means the apex: the domain on its own, with no subdomain.
Point an A record at your VPS
First get the address the internet sees for your server:
curl -4 https://ifconfig.me
ip -brief -4 address showThen create one record at your DNS host: type A, name @, value that address, TTL (time to live) 300. Add a second record for www, either another A with the same address or a CNAME pointing at the apex.
Now prove it resolves, ideally from your laptop rather than from the server itself:
dig example.com A +short
dig @1.1.1.1 example.com A +short
dig @ns1.your-dns-host.net example.com A +shortThe first uses your machine's normal path, caches included. The second skips your local cache and asks a public recursive resolver. The third asks your authoritative nameserver directly, so its answer is the current truth with no cache anywhere in the path. When the third command returns your address and the first does not, your DNS is configured correctly and you are waiting on a cached copy of the old answer.
Resolving is not loading
A name resolving proves DNS works. It proves nothing about your web server. Once dig returns the right address, test the connection:
curl -I http://example.comcurl: (6) Could not resolve host: example.com is a DNS problem. curl: (7) Failed to connect to example.com port 80 after 21 ms: Connection refused is not a DNS problem: the name resolved and the packet arrived, so the issue is that nothing was listening on that port. A request that hangs and then times out usually means a firewall dropped the packet silently instead of refusing it. That is where DNS stops being the subject, and ports and listening sockets plus the ufw firewall rules on your VPS take over. After the connection completes, the rest of the page load is HTTP doing its work.
Why the browser still shows the old host
Nothing propagates. No server pushes your change outward to anyone. Your authoritative nameserver holds the new value the instant you save it, and every cached copy of the previous answer stays valid until its own timer expires. That timer is the TTL, in seconds, that the record carried when it was handed out.
Copies live in more places than people expect: the browser's own short cache, the stub resolver on the machine, the recursive resolver used by that network, and any resolver a VPN installed on the client. Each keeps its copy for up to the TTL it received. Two people on two networks can see two different answers for hours, and both machines are behaving correctly.
Watch the countdown against a caching resolver:
dig @1.1.1.1 example.com +noall +answerRun it twice, a few seconds apart. The TTL in the answer goes down. When it reaches zero, the resolver throws the record away and asks your nameserver again.
There is a second cache that almost nobody accounts for: negative answers. When a resolver is told a name does not exist, it caches that NXDOMAIN as well, for the time set by the last field of your zone's SOA record.
dig example.com SOA +shortThe final number on that line is the negative TTL, often 3600. So looking up staging.example.com before you create it can hide the record from you for a full hour after you create it. Create the record first, then query it.
Changing nameservers is slower than changing a record, and the reason is mechanical. The delegation records in the .com zone are served with a TTL of 172800 seconds, which is two days, so a resolver that cached your old nameservers can keep asking them for that long. This is where the advice to "allow up to 48 hours" comes from. It applies to nameserver changes, not to ordinary record edits.
Plan a migration around the TTL instead of fighting it:
- Lower the record's TTL to 300 and save it.
- Wait longer than the old TTL, so that every cached copy carrying the old value has expired.
- Change the address.
- Once traffic has moved, raise the TTL back to 3600 or higher, because a low TTL means every resolver asks your nameservers far more often.
To clear what your own machine is holding:
resolvectl flush-caches
resolvectl statisticsresolvectl statistics prints a cache section with hit and miss counters, so right after a flush the next lookup shows up as a miss. Browsers keep a separate cache, which means Chrome can still use an old answer after the system cache is empty. Clear that one at chrome://net-internals/#dns. Check /etc/hosts too, because a leftover line there beats DNS on that machine and only on that machine. getent hosts example.com shows the answer the system will really use, /etc/hosts included.
Wildcard certificates are proved with a TXT record
A CA (certificate authority) checks control of a name before it issues a certificate. The HTTP-01 challenge serves a file over port 80 on that exact hostname, which works well for a single name. A wildcard certificate covers *.example.com, an open-ended set of hostnames the CA cannot fetch a file from, so Let's Encrypt issues wildcards only through the DNS-01 challenge. You publish a TXT record at _acme-challenge.example.com holding a token the CA gives you, and control of the zone is the proof.
That makes your DNS host part of certificate renewal. Certbot has to create and delete that TXT record on every renewal without you, so it needs an API and a matching plugin for your provider. When validation fails, the usual message is DNS problem: NXDOMAIN looking up TXT for _acme-challenge.example.com, which means the CA asked before the record was visible: either it was never saved, or a negative answer was still cached. The full procedure lives in the guide to wildcard certificates with the DNS-01 challenge.
When a VPN takes over your resolver
A VPN (virtual private network) client normally replaces the system resolver while it is connected, because sending lookups to the local network would tell that network the name of every site you visit. That is correct behaviour, and it fails in two directions.
If the tunnel comes up and names stop resolving while addresses still work, the resolver the client installed is unreachable from inside the tunnel. ping 1.1.1.1 succeeds and curl https://example.com returns curl: (6) Could not resolve host: example.com. If instead the tunnel comes up and lookups still go to the network you are sitting on, your traffic is tunnelled while the local resolver keeps seeing every name you ask for.
resolvectl statusThat prints the resolver in use for each link, so you can see which one the tunnel installed and whether it is the one you intended. A WireGuard tunnel sets this from the DNS = line in the client config, and fixing DNS when WireGuard takes over the resolver covers the systemd-resolved and resolvconf cases in detail.
The reply codes, and what each one tells you
NXDOMAIN: an authoritative server states that the name does not exist. Check the spelling, check for a doubled domain suffix, and check that you edited the zone your delegation points at.NOERRORwith an emptyANSWER SECTION: the name exists, but it has no record of the type you asked for. Asking forAAAAwhen only anAexists gives exactly this.SERVFAIL: the resolver tried and could not produce an answer. The two usual causes are authoritative servers that never reply, and DNSSEC (domain name system security extensions) validation failing. Test withdig @1.1.1.1 example.com A +cd, which disables validation. An answer with+cdandSERVFAILwithout it means the signatures are the problem, which happens after a nameserver move where the parent still publishes the old DS (delegation signer) record.REFUSED: the server you asked will not answer that question, usually because you pointeddigat an authoritative server for a domain it does not serve.;; connection timed out; no servers could be reached: dig never reached a resolver. That is a network or resolver problem on your side, so the domain is not the subject.
ping: example.com: Temporary failure in name resolution is the same class of failure reported by glibc rather than by dig.
Should you run nameservers on your own VPS?
You can. bind9, knot or nsd will serve your zone from the server, and it teaches you more about DNS than any panel does. The objections are practical. A domain should have at least two nameservers on separate networks, so a single VPS becomes one failure point for every service on the domain, mail included. Nameservers named inside the domain they serve need glue records at the registrar, which is the address of ns1.example.com stored in the parent zone, because otherwise the lookup has no way to start. When a resolver cannot reach your nameserver, it does not fall back to your website: the whole domain disappears for that user. Hosted DNS with an API is the lower-risk choice for most people. Running a caching resolver on your VPS for your own machines is a different job, and a far smaller commitment.
FAQ
Why has my DNS change not propagated yet?
Nothing propagates. Your authoritative nameservers hold the new value the moment you save it, and every resolver that already asked keeps its cached copy until the TTL it received runs out. Ask the authoritative server directly with dig @ns1.your-dns-host.net example.com A +short. If that returns the new address, the change is live and everything left is caching. If you changed nameservers rather than records, expect it to take much longer, because TLD delegations are handed out with a two day TTL.
How do I find which nameservers my domain actually uses?
dig example.com NS +short prints the nameservers answering for the domain now, and dig +trace example.com shows the referral chain from the root, including the delegation the TLD servers hand out. If those names are not the provider whose panel you have been editing, that is your bug. Either edit the records at the provider named in the delegation, or change the delegation at your registrar so it points where you want.
My domain resolves but the site still does not load. What now?
DNS is finished as soon as dig example.com A +short returns your server's address. After that, the problem is the connection. curl -I http://example.com returning Connection refused means nothing is listening on that port. A request that hangs until it times out means a firewall dropped the packet. Check that your web server is running and bound to the public address, then check the firewall on the server and the separate network firewall in your provider's control panel.
Why can I not put a CNAME on my root domain?
A CNAME says that a name is an alias for another name, and a name that has a CNAME is not allowed to carry any other record. Your root domain must carry SOA and NS records in order to exist as a zone, so it cannot also be a CNAME. Use an A record holding the address at the root, or use the provider feature sold as ALIAS, ANAME or CNAME flattening, which stores a name and answers queries with the address that name currently resolves to.