Part 9 — How I Dug Myself Into a Home DNS Hole
There is a very specific kind of danger that comes with personal projects.
Not the obvious danger.
Not:
deadlines
bugs
broken deployments
mysterious Docker errors
No.
The truly dangerous moments begin with innocent thoughts like:
Hmm… there’s probably a cleaner way to do this.
That exact thought recently appeared while working on the mobile version of Needle.
The problem itself seemed simple enough.
The app could already connect:
locally inside my home network
remotely over the internet
I had even implemented logic to switch between the two. And technically speaking? It worked beautifully. There was only one tiny issue.
I suddenly realised I was teaching the app about network topology.
The app knew:
local URLs
remote URLs
switching logic
connectivity states
fallback behaviour
And while all of that sounded clever at first, it also felt suspiciously like the beginning of future suffering.
Because now the app had opinions about:
Wi-Fi
LANs
internet routing
public access
local access
Which raised an uncomfortable philosophical question:
Should an app care where the server physically is?
And honestly? I don’t think it should.
The app should simply know:
This is Needle.
The network infrastructure should handle the rest.
So naturally, instead of continuing work on the actual music app, I disappeared head-first into a DNS rabbit hole.
As one does.
The idea was surprisingly elegant.
Inside my home network:
music.davidrelich.cz
→ 192.168.x.xOutside my home network:
music.davidrelich.cz
→ public server IPSame URL.
Same SSL certificate.
Same backend.
Different routing depending on where the request originates.
Which meant:
local traffic stays local
no unnecessary ISP round-trips
no app-side switching logic
cleaner architecture
less maintenance
fewer future headaches
Beautiful.
There was only one small detail.
My TP-Link router had absolutely no idea how to do any of this.
At which point the normal person response would probably be:
Ah well, never mind.
Unfortunately, I am no longer a normal person.
So instead I deployed AdGuard Home on the Raspberry Pi 5 that already runs approximately half of my digital existence.
This led to the traditional homelab experience:
Docker port conflicts
DNS port conflicts
mysterious networking errors
discovering that NetBird quietly occupied port 53 on another interface
fighting systemd-resolved
and learning far more about local DNS than I ever intended to know
At one point I found myself staring at terminal output showing:
127.0.0.53
172.18.x.x
100.x.x.x…and wondering if I had accidentally opened a Stargate instead of configuring DNS.
Still, after enough tweaking, container wrangling, and mild existential discomfort, something magical happened.
I pointed my router’s DNS settings to the Raspberry Pi.
Then I ran:
dig music.davidrelich.czAnd suddenly my own infrastructure replied.
Not Google.
Not Cloudflare.
Not my ISP.
Mine.
That was one of those quietly satisfying moments where you realise:
Oh no… I actually understand this now.
Which is both empowering and mildly terrifying.
Then came the final step.
I added a local DNS rewrite:
music.davidrelich.cz
→ 192.168.x.xAnd just like that:
local traffic remained inside the house
the app no longer cared where it was
the same URL worked everywhere
and the architecture suddenly became dramatically cleaner
Of course, there was also an unexpected side effect.
AdGuard Home blocks ads.
Meaning I somehow went from:
I want Needle to behave more elegantly on local Wi-Fi
to:
Congratulations, you are now the administrator of your household DNS infrastructure.
Which is not a sentence I expected to say this year.
Then again, I also didn’t expect to build:
a desktop music player
a backend
a web player
an Android app
and now an iPhone app
…simply because modern streaming platforms annoyed me enough.
So honestly?
At this point, deploying my own DNS server feels completely on-brand.
Holy crap, it works.