{"id":86,"date":"2026-01-11T17:41:12","date_gmt":"2026-01-12T01:41:12","guid":{"rendered":"https:\/\/blog.wang-home.net\/?p=86"},"modified":"2026-03-06T23:52:14","modified_gmt":"2026-03-07T07:52:14","slug":"when-cloudflared-deprecates-a-feature-sometimes-you-just-build-your-own","status":"publish","type":"post","link":"https:\/\/blog.wang-home.net\/?p=86","title":{"rendered":"When Cloudflared Deprecates a Feature, Sometimes You Just Build Your Own"},"content":{"rendered":"<p>Late last year, I stumbled across a small but important notice: <a href=\"https:\/\/developers.cloudflare.com\/changelog\/2025-11-11-cloudflared-proxy-dns\/\">Cloudflare plans to remove the proxy-dns command from cloudflared starting February 2, 2026<\/a>. For most people, that might be a footnote. For my home network, it was a ticking clock.<\/p>\n<p>I run two Pi-hole instances, each inside its own VM on separate physical hosts. Both Pi-holes rely on a local cloudflared instance running in proxy-dns mode to provide DNS\u2011over\u2011HTTPS (DoH) upstream resolution. It's a clean setup: Pi-hole handles filtering, cloudflared handles encrypted DNS, and everything hums along.<\/p>\n<p>When I learned that proxy-dns was being deprecated, I started looking at alternatives.<\/p>\n<h2>A Drop\u2011In Replacement \u2014 Or Building My Own<\/h2>\n<p>The Pi-hole community's go\u2011to recommendation is <a href=\"https:\/\/docs.pi-hole.net\/guides\/dns\/dnscrypt-proxy\/\">dnscrypt-proxy<\/a>. It's mature, widely used, and \u2014 importantly \u2014 it can act as an in\u2011place replacement for cloudflared's DoH functionality. I could have swapped it in with minimal effort.<\/p>\n<p>But I saw an opportunity.<\/p>\n<p>I'd been wanting to practice AI\u2011assisted systems coding on a real, self\u2011contained project. Replacing cloudflared's DoH mode felt like the perfect playground: small enough to build in a weekend, but real enough to run in production.<\/p>\n<p>So instead of adopting <code class=\"\" data-line=\"\">dnscrypt\u2011proxy<\/code>, I decided to build my own.<\/p>\n<p>One weekend later, I had a working prototype:<br \/>\n<a href=\"https:\/\/github.com\/whiskeyjay\/homelab\/tree\/main\/rust\/doh-proxy\">https:\/\/github.com\/whiskeyjay\/homelab\/tree\/main\/rust\/doh-proxy<\/a><\/p>\n<p>My goal was simple: a true drop\u2011in replacement. No Pi-hole changes. No port changes. No configuration rewrites. Just:<\/p>\n<ul>\n<li>stop cloudflared<\/li>\n<li>start my DoH proxy<\/li>\n<li>everything continues working<\/li>\n<\/ul>\n<p>And that's exactly how it behaved.<\/p>\n<h2>Real\u2011World Testing<\/h2>\n<p>The proxy has been running in production since December, quietly handling all upstream DNS queries for both Pi-hole instances. To validate it, I ran Steve Gibson's DNS Benchmark against both Pi-holes.<\/p>\n<p>The results were pleasantly uneventful:<\/p>\n<ul>\n<li>no measurable performance regression<\/li>\n<li>no errors in Pi-hole logs<\/li>\n<li>no behavioral differences compared to cloudflared<\/li>\n<\/ul>\n<p>In other words: it behaved exactly like the component it replaced.<\/p>\n<h2>Telemetry: Better Than Expected<\/h2>\n<p>To validate the proxy's behavior further, I captured CPU and memory usage telemetry across both my DoH proxy (for Pi-hole instance 1, the primary instance) and the cloudflared (for Pi-hole instance 2, the backup instance) instances:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.wang-home.net\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-11-172232-scaled.png\" alt=\"7-day telemetry\" \/><\/p>\n<ul>\n<li>The green line (cloudflared on Pi-hole #2) with a steady memory climb, reaching around 70 MB<\/li>\n<li>The yellow line (doh-proxy on Pi-hole #1) fluctuating between roughly 20\u201340 MB<\/li>\n<li>CPU usage for all containers remains low, but my proxy shows tighter bounds.<\/li>\n<\/ul>\n<p>While I didn't benchmark throughput or latency directly, the resource profile looked clean and stable. Combined with the DNS Benchmark results and Pi-hole logs, this gave me confidence that the proxy was behaving as expected \u2014 no regressions, no errors, and no surprises.<\/p>\n<h2>Why Bother?<\/h2>\n<p>Ultimately, the motivation was straightforward: <strong>I wanted a real opportunity to practice AI\u2011assisted coding on a complete, end\u2011to\u2011end systems project.<\/strong> Building a DoH proxy from scratch gave me exactly that \u2014 a contained but meaningful challenge where I could design, implement, test, and deploy a network service that would actually run in production.<\/p>\n<p>And through the process, I gained hands\u2011on experience with the full lifecycle of a DNS proxy: parsing DNS messages, handling DoH requests, managing concurrency, tuning performance, packaging the service, and integrating it cleanly into my existing Pi-hole setup.<\/p>\n<p>What started as a weekend experiment turned into a tool that now quietly powers my home network. If you're running Pi-hole with cloudflared and want a future\u2011proof alternative \u2014 or just want to explore how a minimal DoH proxy works \u2014 feel free to take a look at the code, adapt it, or fork it for your own environment.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Late last year, I stumbled across a small but important notice: Cloudflare plans to remove the proxy-dns command from cloudflared starting February 2, 2026. For most people, that might be a footnote. For my home network, it was a ticking clock. I run two Pi-hole instances, each inside its own VM on separate physical hosts. &#8230; <a title=\"When Cloudflared Deprecates a Feature, Sometimes You Just Build Your Own\" class=\"read-more\" href=\"https:\/\/blog.wang-home.net\/?p=86\" aria-label=\"Read more about When Cloudflared Deprecates a Feature, Sometimes You Just Build Your Own\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[25,26,27],"class_list":["post-86","post","type-post","status-publish","format-standard","hentry","category-homelab","tag-dns","tag-homelab","tag-rust"],"_links":{"self":[{"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/posts\/86","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=86"}],"version-history":[{"count":3,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/posts\/86\/revisions"}],"predecessor-version":[{"id":89,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=\/wp\/v2\/posts\/86\/revisions\/89"}],"wp:attachment":[{"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=86"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=86"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wang-home.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=86"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}