Skip to content

πŸ•ΈοΈ Service: Tailscale (Mesh VPN)

Architecture Overview

Feature Function
Subnet Router Allows remote Tailscale clients to access our Local LAN (192.168.0.x) devices that don't have Tailscale installed.
Exit Node Allows us to route all our phone/laptop internet traffic through this server. Useful for securing our connection on public WiFi.
Kernel Mode Configured with TS_USERSPACE=false for higher throughput and lower latency compared to standard user-space mode.
Health Monitoring Exposes an internal metrics endpoint on port 9002 for Docker healthchecks and Homepage dashboard integration.

Docker Compose File

services:
  tailscale:
    image: tailscale/tailscale:latest
    container_name: tailscale
    hostname: cachyos-homelab
    # HOST MODE: No 'networks' section
    # Uses physical server's IP (192.168.0.100).
    network_mode: host       
    privileged: true         
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - TS_STATE_DIR=/var/lib/tailscale
      # AUTH KEY: Optional. If omitted, check logs for login URL.
      # - TS_AUTHKEY=tskey-auth-xxxxxx 

      # SUBNET ROUTING
      - TS_ROUTES=192.168.0.0/24
      - TS_HOSTNAME=cachyos-homelab

      # Enable Tailscale SSH
      - TS_EXTRA_ARGS=--ssh

      # OPTIMIZATIONS
      - TS_USERSPACE=false    # Performance (Kernel Mode)
      - TS_ACCEPT_DNS=false   # Safety (Protect Host DNS)

      # METRICS & HEALTH
      - TS_ENABLE_HEALTH_CHECK=true
      - TS_ENABLE_METRICS=true
      - TS_LOCAL_ADDR_PORT=0.0.0.0:9002

      #For Homepage Use
      - HOMEPAGE_VAR_TAILSCALE_DEVICE_ID=${HOMEPAGE_VAR_TAILSCALE_DEVICE_ID}
      - HOMEPAGE_VAR_TAILSCALE_KEY=${HOMEPAGE_VAR_TAILSCALE_KEY}

    volumes:
      - ./state:/var/lib/tailscale
      - /dev/net/tun:/dev/net/tun
      # Giving the container read-only access to host's kernel modules so it can load the drivers it needs for iptables
      - /lib/modules:/lib/modules:ro

    healthcheck:
      # wget -q   = Quiet (don't print progress bars)
      # -O -      = Output to stdout (required to combine with -q in BusyBox)
      # --spider  = Don't download, just check headers (Simulates curl -I)
      test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:9002/healthz || exit 1"]
      interval: 1m
      timeout: 10s
      retries: 3
      start_period: 20s

    restart: unless-stopped

The container runs in Host Mode with privileged access to the /dev/net/tun device to enable kernel-level packet routing.

Key Environment Variables

  • TS_ROUTES: Defines the local subnets (e.g., 192.168.0.0/24) to expose to the mesh network.
  • TS_USERSPACE: Set to false to offload packet processing to the kernel, significantly improving upload/download speeds.
  • TS_LOCAL_ADDR_PORT: Opens port 9002 strictly for local metrics. This allows the Docker Healthcheck to verify the service is actually responsive, not just "running".

Post-Installation Setup

For security reasons, Subnet Routes and Exit Nodes must be manually approved in the Admin Console.

  1. Start the container:

    docker compose up -d
    

  2. Go to the Tailscale Admin Console.

  3. Find the machine named cachyos-homelab (or what we have indicated in the hostname in compose file)

  4. Click the Three Dots (...) -> Edit Route Settings.

  5. Enable the toggles for:

  6. βœ… Subnet Routes: 192.168.0.0/24
  7. βœ… Exit Node (optional)

Operational Commands

Check Status: See connected peers and direct connections.

docker exec tailscale tailscale status

View Metrics (Health): Manually verify the health endpoint.

curl http://127.0.0.1:9002/healthz