
Goal
In this article, I'll share my Homelab setup using Tailscale and Docker. While most of my services run on a Synology NAS, this configuration can be achieved on other systems that support Docker.
Key Features
To achieve my goals, I needed to have:
- Services available from anywhere (not just my home network)
- Avoid exposing any port on my router
Disclaimer: I won't cover Docker installation as there are many great tutorials available online.
Components
The setup consists of three main components:
- Tailscale: A VPN service that allows me to connect all devices from anywhere
- Traefik: A router for Docker services that provides easy access to the services
- Technitium: A lightweight DNS server that redirects traffic to the desired services
Tailscale
To set up Tailscale, I created a free account on their website and followed the quickstart guide. This allows me to connect my devices to the VPN network.
Once created, follow the Quickstart Guide to set up your first device to the network.
All Docker Compose projects that we will create will follow this same compose.yml structure:
version: '3.3'
services:
tailscale-dns:
container_name: tailscale-dns
hostname: dns
image: tailscale/tailscale:latest
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
volumes:
- ./tailscale:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- sys_module
restart: unless-stopped
The key component is this setup is the tailscale-traefik service. This allows me to create a connection to the Tailscale network.
It connects using an authentication key that you can set up following this tutorial.
If everything works properly, when you start the service, you should see it in the Tailscale Machines. The machine should show up with the name specified in hostname.
Tailscale + Technitium
Then, I suggest setting up the DNS server, which will allow me to redirect all traffic to the desired Docker host.
I've been using Technitium, but any other like PiHole could work too:
version: '3.3'
services:
tailscale-dns:
container_name: tailscale-dns
hostname: dns
image: tailscale/tailscale:latest
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
volumes:
- ./tailscale:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- sys_module
restart: unless-stopped
dns-server:
container_name: dns-server
image: technitium/dns-server:latest
environment:
- DNS_SERVER_DOMAIN=mydomain.com
volumes:
- ./dns:/etc/dns
restart: unless-stopped
sysctls:
- net.ipv4.ip_local_port_range=1024 65000
network_mode: service:dns
Let's start the service. It should now be accessible via dns:5380.
We'll head back to the configuration later.
Tailscale + Traefik
As I'm hosting most of my services on the same device, I needed a proxy that would redirect all traffic from a given URL to the desired service. Traefik allows me to do this easily by discovering Docker services.
Below is an example compose.yaml file I've been using:
version: '3.3'
services:
tailscale-traefik:
container_name: "tailscale-traefik"
image: tailscale/tailscale:latest
hostname: tailscale-traefik
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
volumes:
- ./tailscale:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- sys_module
restart: unless-stopped
networks:
- intranet
traefik:
image: traefik
container_name: traefik
volumes:
- ./config:/etc/traefik
restart: unless-stopped
network_mode: service:tailscale-traefik
networks:
- intranet
whoami:
image: "traefik/whoami"
container_name: "whoami"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
- "traefik.http.routers.whoami.entrypoints=web"
networks:
- intranet
networks:
intranet:
external: true
Then, I set up a second service traefik which will be a basic traefik setup. I'm not opening any port as the service is accessed directly via the network provided by tailscale-traefik container.
I connect all those services to the same external network for convenience.
For testing purposes, I also add the whoami
service, which is often given as an example with Traefik tutorials. Let's start all of
that!
You should be able to access Traefik WebUI via its Tailscale IP, but let's continue by configuring the DNS server.
Global DNS Configuration
Access your DNS WebUI and head to the section Zone.
Let's create Primary Zone going to mydomain.com.
Then, we need to create the following records if missing:
-
NS Record:
- Name: @
- Name Server: ns.mydomain.com
-
SOA
- Primary Name Server: mydomain.com
- Responsible Person: me@email.com
-
A:
- Name: @
- IPv4: #.#.#.#
-
AAAA:
- Name: @
- IPv6: ####:####:####::####:####
IPv4 and IPv6 correspond to the tailscale IP addresses of the tailscale-traefik machines.
Then, we need to add the dns machine IP address as a Tailscale DNS.
Adding new subdomain
Our DNS server should now be operational. We now need to redirect everything to our services. Let's set up whoami!
Add a new DNS Records:
- CNAME
- Name: whoami
- Domain Name: mydomain.com
If everything is working properly, if you can now access whoami.mydomain.com!
More Services
To add new subdomains, I simply repeated the steps above and updated the DNS records accordingly.
Certificate Authentication
To write...
Conclusion
In this article, I shared my Homelab setup using Tailscale and Docker. With these tools, I was able to create a highly available and easily manageable network of services that can be accessed from anywhere.