Local DNS and TLS termination
Designating specific services as private access only and encrypting them with https requires split-horizon DNS when terminating TLS and hosting the services on seperate machines.
Published: 02/25/2026
In some senses, self-hosting ecosystems seem to grow in “phases”. Maybe the first phase is learning how to host local services and forward ports. Having a git server, file hosting, media streaming, backups, and the like are all really convenient . After that, it seems that learning how to route traffic through a VPN server in order to encrypt remote connections would be the second most important inclusion. I was stuck here for a while. For a long time, I could spin up a new service, and be tinkering with its specific configuration in minutes. After a while I discovered Authentik. I decided it would be a great addition for convenience and security to this environment, but it has some requirements. The biggest requirement, or the third phase of self-hosting to me, is enabling https connections for your local services.
Obtaining a wildcard cert
In order to terminate the https connection, I will be configuring acme to negotiate a DNS-01 challenge using the digitalOcean api. All I have to do is get an API key from digitalOcean, so that the acme client can insert it’s challenge response from Lets Encrypt into the TXT records for my domains DNS. This nixos wiki article made this as simple as a copy/paste and entering my credentials. For the subdomain we will use *.ianmadeit.org in order to obtain the wildcard certificate.
Proxying requests back home
Once I have a wildcard cert I need to proxy the web requests for the local services back to my home server. The way I have this configured is that the VPS is running a VPN server. To which my home server, and the users of the local services will both connect to. Once established, the home server will forward local sub-net traffic through it. This will be explained in further detail why later. The important bit now, is that once my server has an IP from the VPN server, the VPS will proxy the sub-domain requests to it. So, any private services are redirected, in my case to 10.200.0.2. We will direct requests to port 80 on the home server and run another nginx proxy there, so that we don’t have to open a port for every service in our firewall. Once requests are correctly redirected, I need to make sure that only local users can access these specific sub-domains. In order to do this we will use 4 directives. The first 3 will allow the RFC1918 addresses to access the sub-domain, and the final will deny all requests from IP addresses outside those ranges.
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny all;
Resolving sub-domains internally
The goal is to have sub-domains belong to internal only services. These services will only be reachable by people on my local sub-net, or connected to the VPN server. In order for the requests to originate from an RFC1918 address and thus be whitelisted, we need to resolve *.ianmadeit.org to the private IP of the VPS. In my case, 10.200.0.1.
This was a bit of a project unto itself. Again, my only experience with DNS was earlier last month, when I purchased my domain and configured the glue records and zone for my digitalOcean VPS. Therefore, I wanted to make this as much of a learning experience as possible. I decided to get 2 raspberry pi 5s and some cases to serve as my DNS servers. I hadn’t thought about the need for power cables, a mini-HDMI cable, microSD cards and a reader. Once everything came, I learned here that nixos isn’t yet supported on raspberry pi 5. This is a bit of a shame, and changes my plans a little. I had originally planned to do this all with BIND9 in nixos, since it seems to be the standard. But, the idea of having to set a configuration like this up from scratch again in the event of disaster made me want a simpler solution until nixos support comes along. I decided to install Technitium on both of the devices.
What we are trying to configure here is called split-horizon DNS. It boils down to the requests resolving differently based on where they originate. In technitium this is configured by creating a “conditional forwarder zone” for my domain that forwards unresolved requests to a public DNS server of my choice. Within that zone, I create a local A record for *.ianmadeit.org pointing to 10.200.0.1. Because locally defined records take precedence, VPN clients resolve subdomains to the VPS’s private VPN address, while the base domain (which has no local override) is forwarded to a public DNS server and resolves to the VPS’s public IP.

Now that everything resolves correctly when using my local DNS servers, I need to make it so that for remote, and local users, my DNS servers are the default. There is a way to set the DNS servers that wireguard clients use while connected I found here. Combining this with routing only my local sub-net and the vpn sub-net through the tunnel from earlier, we have a solution for remote users. For local users, I learned that this would require a DHCP server. Once configured inside technitium, this would push a DNS configuration, including which servers to use, to the clients upon receiving a local IP address. Then I just need to disable my router’s DHCP server.
Insights
With that, everything should work. The website should still be publicly available, while the sub-domain private services should be guarded behind the nginx reverse proxy. Users who have been given access either to my local network or the VPN network should be able to reach those private services by resolving them to the VPS so it can terminate TLS and filter access. Linux users mileage may vary as they may have to edit their resolv.conf to update which DNS servers they use, but maybe that could be a bash script for a different day.
This project did end up costing quite a bit more than I had originally expected. Mostly because I somehow totally forgot to get storage for the DNS servers. That’s something I definitely have to look out for going forward when a project relies on new hardware. I learned a ton about DNS from this project. Things like DNS-01 challenges, split-horizon DNS, dynamic DNS, DNS over HTTPS, and recursive vs iterative resolution were all foreign concepts to me before this project. I also got to learn a bit about DHCP and broadcast protocols, because a switch on my network was hosting a second DHCP server and hi-jacking the requests for IP addresses.
All in all, This project was a lot of fun, and granted me a lot more control over my network in general. One of the greatest benefits not even mentioned here is the ability to control name resolution for devices at the network level, enabling me to block advertisers, trackers, and malicious actors for all devices on my network.