Files
infrastructure/docs/09-TAILSCALE-VPN.md
T
Kaloyan DanchevandClaude Opus 5 666b9baa5c docs: Unraid re-enrolled on Tailscale as 100.100.208.69
Unraid's Tailscale plugin node had been logged out since roughly May 2026.
Re-enrolled as xtrm-unraid (100.100.208.69); the stale 100.100.208.70 node
was deleted first, so the tailnet issued a new address.

Dropped the old 192.168.31.0/24 advertisement — that subnet is only the
macvlan shim and nothing reachable lives there. No LAN subnet routes are
advertised from Unraid; the MikroTik container stays primary. accept-routes
and accept-dns stay off, the former because Unraid sits on 192.168.10.0/24
and would otherwise loop.

Tailscale SSH enabled, since sshd binds only 192.168.10.20 and
192.168.31.250 and so never listens on the Tailscale IP. Port forwarding
over it verified.

Exit node advertised, pending approval in the admin console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-11-03 21:42:14 +02:00

11 KiB

MikroTik Tailscale Container Setup

Last Updated: 2026-02-06


Overview

Tailscale VPN running as a container on MikroTik hAP ax³, providing remote access to the home network via the Tailscale mesh network.


Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                    MikroTik hAP ax³ (192.168.10.1)                  │
│                                                                     │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                 Container Network (172.17.0.0/24)            │   │
│  │                                                              │   │
│  │   ┌─────────────────────┐    ┌─────────────────────────┐    │   │
│  │   │   AdGuard Home      │    │      Tailscale          │    │   │
│  │   │   172.17.0.2        │    │      172.17.0.3         │    │   │
│  │   │   veth-adguard      │    │      veth-tailscale     │    │   │
│  │   └─────────────────────┘    └─────────────────────────┘    │   │
│  │            │                           │                     │   │
│  │            └───────────┬───────────────┘                     │   │
│  │                        │                                     │   │
│  │                 Gateway: 172.17.0.1                          │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                      │
│                         NAT Masquerade                              │
│                              │                                      │
│                          WAN (ether1)                               │
└──────────────────────────────┬──────────────────────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │   Tailscale Network │
                    │   100.x.x.x mesh    │
                    │                     │
                    │   Home Router IP:   │
                    │   100.74.219.35     │
                    └─────────────────────┘

Container Details

Setting Value
Image tailscale/tailscale:latest
Interface veth-tailscale
Container IP 172.17.0.3/24
Gateway 172.17.0.1
Tailscale IP 100.74.219.35
Root dir usb1/tailscale/root
State mount usb1/tailscale → /var/lib/tailscale
DNS 8.8.8.8
Start on boot Yes
Networking mode Userspace (TS_USERSPACE=true)

Environment Variables

Variable Value Purpose
TS_AUTHKEY tskey-auth-... One-time auth key (used during setup)
TS_STATE_DIR /var/lib/tailscale Persistent state directory
TS_USERSPACE true Required for MikroTik containers (no /dev/net/tun)

Network Configuration

veth Interface

/interface veth add address=172.17.0.3/24 gateway=172.17.0.1 name=veth-tailscale

Gateway IP on Interface

/ip address add address=172.17.0.1/24 interface=veth-tailscale comment="Tailscale container gateway"

NAT Masquerade for Internet Access

/ip firewall nat add chain=srcnat action=masquerade src-address=172.17.0.0/24 out-interface-list=WAN comment="Container network NAT"

Firewall Forward Rules

/ip firewall filter add chain=forward action=accept dst-address=172.17.0.0/24 comment="[Container] Forward to container network"
/ip firewall filter add chain=forward action=accept src-address=172.17.0.0/24 comment="[Container] Forward from container network"

Container Setup Commands

Create Mounts

/container mounts add list=ts-state src=usb1/tailscale dst=/var/lib/tailscale

Create Environment Variables

/container envs add list=ts-env key=TS_STATE_DIR value=/var/lib/tailscale
/container envs add list=ts-env key=TS_USERSPACE value=true
/container envs add list=ts-env key=TS_AUTHKEY value=<your-auth-key>

Create Container

/container add remote-image=tailscale/tailscale:latest interface=veth-tailscale \
    root-dir=usb1/tailscale/root mountlists=ts-state envlists=ts-env \
    dns=8.8.8.8 start-on-boot=yes logging=yes

Management

Check Container Status

/container print

View Logs

/log print where topics~"container" and message~"tailscale"

Start/Stop Container

/container start [find name~"tailscale"]
/container stop [find name~"tailscale"]

Troubleshooting

Container Won't Start (Exit Status 1)

Cause: Missing /dev/net/tun device (default for Tailscale)

Solution: Enable userspace networking mode:

/container envs add list=ts-env key=TS_USERSPACE value=true

Can't Reach Internet from Container

Cause: Missing NAT masquerade or gateway IP

Solution:

  1. Verify gateway IP on veth interface:
/ip address print where interface=veth-tailscale
  1. Verify NAT masquerade rule:
/ip firewall nat print where src-address=172.17.0.0/24

Container Not Connecting to Tailscale

  1. Check DNS resolution works (logs should show no timeout)
  2. Verify auth key is valid and not expired
  3. Check firewall isn't blocking outbound HTTPS

Tailscale Network Devices

Tailscale IP Device Status
100.74.219.35 MikroTik hAP ax³ (container) Online
100.100.208.69 xtrm-unraid (Unraid plugin) Online
100.100.208.70 xtrm-unraid (old node, deleted 2026-11-03) Removed
100.112.103.7 hapax3 (old native install) Offline
100.75.93.123 mikrotik-tailscale (previous container) Offline

Important Notes

  1. Userspace Networking Required: MikroTik containers don't have /dev/net/tun access, so TS_USERSPACE=true is mandatory

  2. Auth Key: After initial authentication, the key is no longer needed - state is persisted in the mount

  3. Container Network: Both AdGuard and Tailscale share the 172.17.0.0/24 network but have separate veth interfaces

  4. Accept Routes: If subnet routing is needed, add TS_EXTRA_ARGS="--accept-routes" to environment


Unraid Tailscale Plugin Node — 2026-11-03

The Unraid server runs its own Tailscale node via the Tailscale plugin (not a container), separate from the MikroTik container documented above. It had been logged out since roughly May 2026 and was re-enrolled on 2026-11-03.

Item Value
Tailscale IP 100.100.208.69
MagicDNS name xtrm-unraid.tailf789e1.ts.net
Daemon /usr/local/sbin/tailscaled 1.96.2, -tun tailscale1
State dir /boot/config/plugins/tailscale/state (survives reboot)
Previous IP 100.100.208.70 — stale node deleted, so a new IP was issued

Prefs set

Pref Value Reason
--advertise-routes none The old 192.168.31.0/24 advertisement was dropped. That subnet is only the macvlan shim (br0-shim holds 192.168.31.250/32 with one host route to 192.168.31.4) — nothing reachable lives there.
LAN subnet routing not advertised The MikroTik container is primary for 192.168.10.0/24, .20, .25, .30. A second advertiser for a subnet Unraid itself sits on would create a routing conflict.
--advertise-exit-node on Redundant with the hAP today, kept as a fallback on the 24/7 box. Needs approval in the admin console before it appears in tailscale exit-node list.
--accept-routes false Critical. Unraid is on 192.168.10.0/24; accepting the hAP's route for its own subnet would loop. This is why tailscale status reports the health warning "Some peers are advertising routes but --accept-routes is false" — expected here, not a fault.
--accept-dns false Keeps local AdGuard resolution intact (Unraid AdGuard is config master).
--ssh on Tailscale SSH. Needed — see the sshd caveat below.

SSH over Tailscale — the sshd caveat

/etc/ssh/sshd_config on Unraid binds explicitly and has no wildcard:

Port 422
ListenAddress 192.168.10.20   # br0
ListenAddress 192.168.31.250  # br0-shim

So sshd does not listen on 100.100.208.69. Port 422 on the Tailscale IP is closed and stays closed unless a ListenAddress is added — which needs a go script, because Unraid regenerates this file per interface at every boot.

Access on the Tailscale IP is served by Tailscale SSH on port 22, handled by tailscaled itself and authenticated by tailnet identity rather than by an SSH key:

# direct, independent of the MikroTik subnet router
ssh root@100.100.208.69
ssh root@xtrm-unraid.tailf789e1.ts.net

# port forward — verified 2026-11-03 (Unraid web UI returned HTTP 302)
ssh -N -L 18089:127.0.0.1:80 root@100.100.208.69

The default tailnet ACL uses action: "check", so the first connection in each period opens a browser re-auth prompt. Fine interactively, but it will stall an unattended tunnel; switching that rule to accept for autogroup:self in the admin console removes the prompt.

The other path — via the MikroTik subnet router

Independent of the Unraid node and still working:

ssh -i ~/.ssh/id_ed25519_unraid -p 422 -N -L 18088:127.0.0.1:80 root@192.168.10.20

Forwarding works here only because Unraid's stock sshd config denies it globally and re-enables it for root alone:

AllowTcpForwarding no           # limetech - disallow forwarding but see below
...
Match Group root
AllowTcpForwarding yes          # limetech - permit only root SSH tunneling

Any non-root account added later will not be able to open tunnels.

Open item

  • Approve the advertised exit node for xtrm-unraid in the Tailscale admin console (Machines -> xtrm-unraid -> Edit route settings).