Setup Tailscale Subnet Router on Proxmox
Overview
This guide configures the Proxmox host as a single Tailscale subnet router so every LXC, Docker container, and LAN device can reach Tailscale peers without installing Tailscale individually. One central authentication, one place to manage.
Architecture:
- Proxmox host (
192.168.0.2) runs Tailscale and advertises the LAN subnet192.168.0.0/24 - MikroTik router (
192.168.0.1) routes Tailscale CGNAT traffic (100.64.0.0/10) through Proxmox - LXCs and Docker containers reach Tailscale peers transparently — no per-LXC config
1 2 3 4 5 6 7 | |
[!NOTE]
100.64.0.0/10is the Tailscale CGNAT range (RFC 6598). Every Tailscale node gets an IP in this block, so one route covers all current and future peers. It is reserved and not used on the public internet — safe to route locally.
Proxmox Host Configuration
1. Install Tailscale
1 | |
Installs tailscale and enables tailscaled.service.
2. Enable IP forwarding
Persistent via sysctl drop-in:
1 2 3 | |
3. Bring Tailscale up as subnet router
1 2 3 4 | |
Open the printed login URL in a browser to authenticate.
| Flag | Purpose |
|---|---|
--advertise-routes=192.168.0.0/24 |
Tells the tailnet that Proxmox can forward traffic for the LAN. Other peers can reach LXCs by their LAN IPs. |
--accept-routes |
Lets Proxmox use subnets advertised by other Tailscale nodes. |
--hostname=proxmox |
Name shown in Tailscale admin console and via MagicDNS. |
4. Add MASQUERADE for outbound Tailscale traffic
Without this, packets leave Proxmox with the LXC's LAN source IP (192.168.0.x), which Tailscale peers don't know how to reply to. MASQUERADE rewrites the source to Proxmox's Tailscale IP.
1 | |
[!NOTE] Tailscale's built-in subnet-router masquerade only handles the inbound direction (tailnet → LAN). The outbound direction (LAN → tailnet) needs this manual rule.
5. Persist iptables rule
1 2 | |
The MASQUERADE rule is saved to /etc/iptables/rules.v4 and reloaded on boot.
Tailscale Admin Console Configuration
6. Approve the advertised subnet route
- Go to https://login.tailscale.com/admin/machines
- Find the
proxmoxrow → ⋯ menu → Edit route settings - Toggle ON:
192.168.0.0/24→ Save
7. Disable key expiry on Proxmox
Without this, the node key expires (default 180 days) and the entire subnet router goes offline silently — every LXC loses Tailscale connectivity at once.
- Same machine row → ⋯ menu → Disable key expiry
- Confirm. The expiry column should change to Disabled.
[!NOTE] Disable key expiry on always-on infrastructure (subnet routers, servers). Keep it enabled on personal devices (laptop, phone) where re-auth is natural.
MikroTik Router Configuration
8. Add static route for Tailscale CGNAT
IP→Routes→New- Dst. Address:
100.64.0.0/10 - Gateway:
192.168.0.2 - Comment:
Tailscale via proxmox - Defaults are fine:
distance=1,scope=30,target-scope=10
1 | |
[!NOTE] If MikroTik's WAN IP is in
100.64.0.0/10(some ISPs assign CGNAT IPs to WAN), narrow the route or your WAN traffic will go to Proxmox. Check with/ip address print where address~"100\\.".
Verification
9. Verify from Proxmox host
1 2 | |
Expect to see all peers and successful ping.
10. Verify from an LXC
1 2 3 4 | |
[!NOTE] First ping may show
Redirect Host (New nexthop: 192.168.0.2)— this is MikroTik telling the LXC the next-hop is on the same subnet. Linux honors the redirect automatically. Subsequent packets bypass MikroTik (TTL drops by one — direct path through Proxmox only).
11. Verify from a Docker container
1 | |
TTL=62 confirms the chain: container → Docker bridge → LXC eth0 → Proxmox → tailscale0.
Adding More LXCs
Nothing extra needed. Any new LXC on 192.168.0.0/24 automatically reaches Tailscale peers via:
- Default gateway → MikroTik (
192.168.0.1) - MikroTik static route → Proxmox (
192.168.0.2) - Proxmox MASQUERADE → tailscale0 → peer
The same applies to any LAN device (laptop, NAS, etc.).
Troubleshooting
Ping to peer fails with 100% loss from LXC, but works from Proxmox
The MASQUERADE rule is missing or not active. Verify:
1 | |
Expect: MASQUERADE all -- * tailscale0 0.0.0.0/0 0.0.0.0/0
tcpdump confirms packets leave but no reply
Run on Proxmox:
1 | |
If outbound shows source 192.168.0.x instead of 100.79.97.44, MASQUERADE isn't applying. Re-add the rule.
Subnet route not active in admin console
Even with --advertise-routes set, the route is dormant until approved. Check tailscale status --json for PrimaryRoutes — empty means not approved.
LXCs lose Tailscale connectivity after ~6 months
Node key on Proxmox expired. SSH into Proxmox and run tailscale up to re-authenticate. Prevent by disabling key expiry (Step 7).