Homelab Setup

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:

  1. Services available from anywhere (not just my home network)
  2. 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:

  1. Tailscale: A VPN service that allows me to connect all devices from anywhere
  2. Traefik: A router for Docker services that provides easy access to the services
  3. 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:

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:

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.