Accessing your services inside your LAN without IPs
Got a load of self-hosted services and can't remember all their ports? Need to access that service with secure https rather than plain old http but don't want to make it public? Maybe you just want to be able to type myservice.mycooldomain.com
instead of an IP and port? This is for you.
It's totally possible and pretty easy to access your services via their own URL, and have it served locally. What do I mean? Well let's take Radarr for instance. If we assume you've set up a docker container for it on the default port of 7878, and your machine's LAN IP is 192.168.0.10, you probably know you can access the GUI through your browser by typing http://192.168.0.10:7878
into the address bar. You may also know that you can set up a reverse proxy to access it remotely by an URL you would define, something like https://radarr.mycooldomain.com
.
Using that last method is great, but it basically takes a longer route through a public space (the internet) rather than keeping the request inside your LAN. Well, there's a way to have both! Today we're going to look at SWAG (an nginx-based reverse proxy) and AdGuard, both on a macvlan
network.
Prerequisites
Before we get started, you'll need the following:
- Docker and docker-compose installed on your machine
- The ability to SSH / use CLI/terminal on your machine, or use Portainer to spin up your stacks
- Some sort of access and relevant permissions to manage and create new directories
- A Fully Qualified Domain Name (FQDN, e.g.
pointtosource.com
) - A reverse proxy already set up for the service you want, on its own docker network (for instance called
proxy
) with the relevant SSL certificate(s) (check out my SWAG article for some info on how to do that if you haven't already) - Admin access to your router
- A router which allows you to set a custom DNS
Setting up your MacVlan network
This is a type of network which allows us to give a docker container its own IP on our LAN's subnet (i.e. if your LAN is 192.168.0.0/24
, you could assign the container an IP of 192.168.1.100
and it will be accessible at that IP without needing to use a port).
First, we need to find the parent network of your machine's IP (make sure you know what your machine's IP is already):
- SSH into your machine and if necessary access the root user by typing
sudo su -
followed by your password
if you don't want to access root, then append each docker command below with sudo
- Type
ifconfig
followed byEnter
, and you'll get a chunk of network information - Scroll down the list, looking for your machine's IP in the blocks on the right. It should be towards the bottom
- Once you've located your IP, take note of the network adapter which is on the left hand side, and will likely be something like
eth0
oreth1

So we've identified the parent network, here it's eth1
. Next we need to specify the macvlan network and set it up. The format goes like this (everything in [ ]
brackets will be specific to your setup):
docker network create -d macvlan subnet=[MyLANIP/24] --gateway=[MyLANgateway] -o parent=[eth1] [network name]
So let's say the subnet was 192.168.0.0/24
, the gateway would be 192.168.0.1
, you've found your parent network is eth1
and you want to call the network mymacnetwork
:
docker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=eth1 mymacnetwork
remember, all commands and information typed into the cli are case sensitive
That's the macvlan set up. Now to create AdGuard and add it to your macvlan:
- Still in SSH, create your AdGuard container (you can use the following as a template, don't forget to create the relevant folders/directories)
networks:
mymacnetwork:
external: true
proxy:
external: true
services:
adguard: #ad blocking and local DNS, set your router's DNS to this container's IP address
container_name: adguard
image: adguard/adguardhome
ports:
- 3000:3000/tcp
- 54:53/tcp
- 54:53/udp
- 67:67/udp
- 67:67/tcp
- 69:68/tcp
- 69:68/udp
- 853:853/tcp
volumes:
- ./adguard/work:/opt/adguardhome/work
- ./adguard/conf:/opt/adguardhome/conf
restart: unless-stopped
networks:
mymacnetwork:
ipv4_address: 192.168.0.200 #change as necessary to an UNUSED IP on your network
proxy:
Once up and running, you should be able to access your AdGuard instance at http://192.168.0.200
(or whatever IP you set).
Alternative Compose
If you wanted to create the macvlan network as part of your compose file, you could use this instead:
networks:
mymacnetwork:
name: mymacnetwork
driver: macvlan
driver_opts:
parent: eth1
ipam:
config:
- subnet: 192.168.0.0/24
proxy:
external: true
services:
adguard: #ad blocking and local DNS, set your router's DNS to this container's IP address
container_name: adguard
image: adguard/adguardhome
ports:
- 3000:3000/tcp
- 54:53/tcp
- 54:53/udp
- 67:67/udp
- 67:67/tcp
- 69:68/tcp
- 69:68/udp
- 853:853/tcp
volumes:
- ./adguard/work:/opt/adguardhome/work
- ./adguard/conf:/opt/adguardhome/conf
restart: unless-stopped
networks:
mymacnetwork:
ipv4_address: 192.168.0.200 #change as necessary to an UNUSED IP on your network
proxy:
Setting up Adguard
This isn't something I'm going to go into, however you do need to make sure you set your router's DNS to your Adguard IP address (in this case, it's 192.168.0.200
). Each router brand does this in a different way, make sure you know how to do it for yours.
Setting up local URL routing
Let's go back to our https://radarr.mycooldomain.com
example. You've already got your reverse proxy set up to serve radarr to any request for that URL when received externally. But we want to serve it when the request stays internal to our network only.
Well, the macvlan you created is going to come in useful again, as you're going to add your reverse proxy to it on its own IP (but you'll also keep it on the proxy network).
Assuming your reverse proxy container is called swag
, and we're adding it to the same mymacnetwork
with an IP address of 192.168.0.201
(assuming that IP is currently unused):
- SSH into your machine
- Type the following (modify to match your setup)
docker network connect --ip 192.168.0.201 mymacnetwork swag
And done. Why did we do this and not just leave our RP on its own network? Well AdGuard has an option to route DNS requests locally to any IP. But it CANNOT route them to specific ports. So whatever was going to serve your request needed to be on its own IP, and now it is.
Right, back to AdGuard, and we're looking for a screen called DNS rewrites
:

Once inside the DNS rewrites
page:

- Click
Add DNS rewrite
- In the pop-up modal, add either your specific
radarr.mycooldomain.com
(nohttp
orhttps
) OR, to catch all subdomains you create a reverse proxy for,*.mycooldomain.com
- Then add the IP address you set for your reverse proxy in the next box, and press
Save
Ok great. Before, you would type radarr.mycooldomain.com
into your browser, and it would come up with your radarr GUI. Now it.... does the same? So how do you know it's working?
There's a way to check this, using the nslookup
tool in CLI/terminal:
nslookup radarr.mycooldomain.com
If you'd run this before creating the DNS rewrite, it would have popped up with the server and IP address of whichever public DNS you were using - it could have been Google and 8.8.8.8, or Cloudflare and 1.1.1.1. Now, it should show adguard
as the server name, and the address would be 192.168.0.200
.
Below that, you should see the name of your request radarr.mycooldomain.com
followed by your reverse proxy's IP address 192.168.0.201
.
If that's what's showing, then congrats, you've now got local DNS serving you your apps using your domain, all with SSL, without ever leaving your network.
PiHole instead of AdGuard
Assuming you've already got PiHole set up, it's essentially exactly the same process.
- After logging in, click
Local DNS
in the left hand navigation panel, thenDNS Records
in the drop down - Add your domain (without a
*
and without thehttp
orhttps
) - Add the IP address (e.g.
192.168.1.201
) - Click
Add
, let it do it's thing, and then test in the same way as above
Related Articles



Have some feedback or something to add? Comments are welcome!
Please note comments should be respectful, and may be moderated