{"id":889,"date":"2026-08-14T22:44:29","date_gmt":"2026-08-14T22:44:29","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=889"},"modified":"2026-08-14T22:44:29","modified_gmt":"2026-08-14T22:44:29","slug":"vps-local-dns-resolver-unbound","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/","title":{"rendered":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy"},"content":{"rendered":"\n\n<p class=\"wp-block-paragraph\">Every DNS lookup your server makes \u2014 package installs, API calls, database connections, outbound webhooks \u2014 goes to whatever resolver the OS or your provider configured, often hundreds of milliseconds away and frequently logged by a third party. Running Unbound locally turns that into a near-instant cache hit, adds DNSSEC validation, and keeps your query history on your own machine. This guide walks through installation, configuration, verification, and the tuning options that matter on a small VPS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Run a Local Resolver<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Latency<\/strong> \u2014 cached lookups resolve in under a millisecond instead of 10\u201350 ms to an upstream resolver.<\/li><li><strong>Privacy<\/strong> \u2014 query logs stay on your server; no third-party resolver sees your traffic patterns.<\/li><li><strong>DNSSEC<\/strong> \u2014 Unbound validates responses by default, blocking spoofed answers.<\/li><li><strong>Control<\/strong> \u2014 you decide which upstreams to use and can block or redirect domains.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Install and Configure Unbound<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>apt install -y unbound\nsystemctl enable --now unbound<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace the default config with a minimal, hardened setup that listens on localhost only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; \/etc\/unbound\/unbound.conf &lt;&lt;&#039;EOF&#039;\nserver:\n    interface: 127.0.0.1\n    port: 53\n    do-daemonize: no\n    access-control: 127.0.0.0\/8 allow\n    access-control: ::1 allow\n    do-ip6: yes\n    do-udp: yes\n    do-tcp: yes\n    prefetch: yes\n    prefetch-key: yes\n    qname-minimisation: yes\n    aggressive-nsec: yes\n    rrset-cache-size: 20m\n    msg-cache-size: 10m\n    hide-identity: yes\n    hide-version: yes\nEOF\nsystemctl restart unbound<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On a typical VPS this uses 30\u201360 MB of RAM \u2014 a fair trade for removing DNS from your request path.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Point the System at It<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On modern systemd-based distributions, tell systemd-resolved to use 127.0.0.1, or skip resolved entirely and write <code>\/etc\/resolv.conf<\/code> directly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Option A: systemd-resolved\nmkdir -p \/etc\/systemd\/resolved.conf.d\necho -e \"[Resolve]\\nDNS=127.0.0.1\\nDNSStubListener=no\" &gt; \/etc\/systemd\/resolved.conf.d\/unbound.conf\nsystemctl restart systemd-resolved\n\n# Option B: direct resolv.conf\necho \"nameserver 127.0.0.1\" &gt; \/etc\/resolv.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For Docker containers, set <code>dns: 127.0.0.1<\/code> in <code>docker-compose.yml<\/code> so containers share the host cache instead of each resolving independently.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Much Faster Does It Get?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The win is largest for repeat lookups. A server that makes the same API, database, or package-manager queries over and over turns every subsequent lookup into a cache hit. On a typical VPS the difference is dramatic:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Scenario<\/th><th>Typical resolution time<\/th><\/tr><\/thead><tbody><tr><td>First lookup through local Unbound (DNSSEC validated)<\/td><td>10\u201350 ms<\/td><\/tr><tr><td>Repeat lookup, cached locally<\/td><td>0.1\u20131 ms<\/td><\/tr><tr><td>Lookup via distant provider resolver<\/td><td>20\u201380 ms, repeated every time<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Applications that resolve a hostname per connection \u2014 which is most of them \u2014 stop paying the round trip on every single connection after the first. Web requests that previously waited on DNS now proceed immediately, which shows up directly in time-to-first-byte measurements.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify Caching and DNSSEC<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>dig example.com @127.0.0.1 +time\ndig +dnssec example.com @127.0.0.1 | grep -E 'status|flags'\nunbound-control stats | grep -E 'num.query|num.cache'<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Lookup type<\/th><th>Typical latency<\/th><\/tr><\/thead><tbody><tr><td>Cache hit (repeated lookup)<\/td><td>0.1\u20131 ms<\/td><\/tr><tr><td>First lookup, valid DNSSEC<\/td><td>10\u201350 ms<\/td><\/tr><tr><td>Upstream resolver (no local cache)<\/td><td>10\u201350 ms + round trip to their location<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Tuning That Matters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The config above already enables the three settings with the biggest impact: <code>prefetch<\/code> refreshes popular records just before they expire, <code>qname-minimisation<\/code> sends only the necessary label to each upstream and improves privacy, and <code>aggressive-nsec<\/code> serves negative answers from cache. If you see many uncached lookups in <code>unbound-control stats<\/code>, raise <code>rrset-cache-size<\/code>; if memory is tight, lower it. A good rule of thumb is 20 MB of RRset cache per 1 GB of VPS RAM \u2014 most small servers never need more. Enable the <code>unbound-control<\/code> socket if you want to flush caches after DNS changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unbound-control-setup\necho \"remote-control:\\n    control-enable: yes\\n    control-interface: 127.0.0.1\" &gt;&gt; \/etc\/unbound\/unbound.conf\nsystemctl restart unbound\nunbound-control flush_zone example.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Flushing a zone is useful when you change a record and do not want to wait out the TTL \u2014 <code>flush_zone<\/code> clears just that domain instead of dumping the whole cache and paying the warm-up cost again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Security: Lock the Resolver Down<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An open recursive resolver is a security incident waiting to happen \u2014 attackers will find it and use it for DNS amplification attacks. The config above already restricts access to localhost via <code>access-control<\/code>. If you want containers on a Docker bridge or a private network to use it, add only those subnets explicitly and never expose port 53 publicly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># allow only the Docker bridge and loopback\naccess-control: 172.16.0.0\/12 allow\naccess-control: 0.0.0.0\/0 refuse<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then verify from outside that the port is not reachable: <code>nmap -p 53 YOUR_IP<\/code> should show the port filtered or closed. If it is open, fix your firewall before doing anything else \u2014 an open 53 is how resolvers get recruited into botnets.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Worth the Ten Minutes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A local resolver removes a variable source of latency and a privacy leak in one small install. Combined with the other basics \u2014 caching at the web layer and a tuned kernel \u2014 it is exactly the kind of low-effort change that makes a <a href=\"https:\/\/virtualserversvps.com\/\">VPS feel faster<\/a> without buying more hardware. If you are evaluating providers, <a href=\"https:\/\/virtualserversvps.com\/cloud-vps-benefits.html\">cloud VPS plans with solid network stacks<\/a> make the most of a local cache, since every uncached lookup still crosses the network.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting Common Issues<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Port 53 already in use<\/strong> \u2014 systemd-resolved binds 127.0.0.53 by default; disable its stub listener (<code>DNSStubListener=no<\/code> above) and restart, then check <code>ss -tulpn | grep :53<\/code>.<\/li><li><strong>DNS works on the host but not in Docker<\/strong> \u2014 containers use their own resolver settings; set <code>dns: 127.0.0.1<\/code> per service or add <code>--dns<\/code> to the run command.<\/li><li><strong>Lookups slow after reboot<\/strong> \u2014 the cache is in memory; warm-up takes a few minutes under normal traffic, which is expected.<\/li><li><strong>DNSSEC validation failures<\/strong> \u2014 a domain with broken DNSSEC will refuse to resolve; that is the validator working as intended, not a misconfiguration.<\/li><\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>Every DNS lookup your server makes \u2014 package installs, API calls, database connections, outbound webhooks \u2014 goes to whatever resolver the OS or your provider configured, often hundreds of milliseconds&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-889","post","type-post","status-publish","format-standard","hentry","category-vps-guides-tutorials"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy - Virtual Servers VPS Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy\" \/>\n<meta property=\"og:description\" content=\"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-14T22:44:29+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/\",\"name\":\"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-08-14T22:44:29+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy - Virtual Servers VPS Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/","og_locale":"en_US","og_type":"article","og_title":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy","og_description":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy","og_url":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-08-14T22:44:29+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/","url":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/","name":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-08-14T22:44:29+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/vps-local-dns-resolver-unbound\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Setting Up a Local DNS Resolver with Unbound on Your VPS: Lower Query Latency and More Privacy"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=889"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/889\/revisions"}],"predecessor-version":[{"id":890,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/889\/revisions\/890"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}