I have a Raspberry Pi home server that I can remotely access through a tinc VPN tunnel with my VPS. Most services can be accessed through the tunnel with addresses like plex.crawford.kiwi, but some of them are only available on my local network, for example, SMB and SSH. Accessing these services from the local network is actually more difficult than the services available remotely for two reasons:
- The local IP address may change. Most routers let you configure a MAC address based IP reservation, however one of my original goals for this system was that it should be able to work even in situations where I don’t have control of the router.
- Differences between networks. The local address space (e.g.: 192.168.1.xx) varies between networks and the address you want to reserve may already be taken. This means that if you change your network you may also need to change your computers configuration to access the Pi at it’s new address.
- IP addresses are hard to remember. There is a reason DNS was invented! DNS allows a friendly URL to map to the underlying IP address.
My solution is to run a DNS server on my VPS that fetches the IP address from the Pi through the VPN tunnel when a request is made. This means to access my Pi through the local network, I just punch in an address like local.pi.crawford.kiwi
and I can access it no matter what it’s local IP address is!
The DNS server that runs on my VPS server is something I created called local-address-dns. This runs a DNS server using dnsd and upon an incoming DNS request it connects to local-address-dns-client-rpi running on my Pi. local-address-dns-client-rpi is a simple web server that returns the Pi’s IP address on one of it’s network interfaces. An NS record on my domain points addresses like local.pi.crawford.kiwi
to my VPS to be handled by local-address-dns.
This works great for services like SSH and SMB which tend to use a default port, but what about when you run multiple web-based serices off the same machine? For example, if you run Plex on port 32400 and Deluge on port 8112.
In these cases, I’d love to just use a domain name like plex.local.pi.crawford.kiwi
over having to remember local.pi.crawford.kiwi:32400
!
Theres a few answers to this question. One is to configure NGINX to proxy the service based on the domain name being accessed, or simply to redirect to another URL based on the domain name being accessed.
I went with the redirect based approach and created virtual-host-redirector for this purpose. This makes configuration easy as you just need to setup a rules.json
file with host to URL mappings.
With either of these approaches you’ll need to:
- Make sure you aren’t running anything else on port 80. If you are, just reconfigure this service to another port and setup a redirect rule for it.
- Configure a wildcard CNAME record with your DNS provider to the local-address-dns managed domain name. For example, mine is a CNAME record of
*.local.pi.crawford.kiwi
pointing atlocal.pi.crawford.kiwi
.
Edit, 1 July 2018: I’ve added some more details about another project of mine called virtual-host-redirector
.
Edit, 12 September 2023: I’ve removed the Docker images for local-address-dns
, local-address-dns-client-rpi
and virtual-host-redirector
made them all Public Archives on GitHub. The code is still available for inspiration but is not being maintained - especially as they were getting very behind on security updates.