Tailscale Subnet Router — Proxmox LXC¶
A dedicated unprivileged LXC container that acts as a Tailscale subnet router, advertising your home LAN (192.168.0.0/24) to your tailnet. This allows remote access to every device on the LAN — including the Proxmox host and its web UI — without installing Tailscale on the hypervisor itself.
This container is a high-value target
The subnet router is the single container that, if compromised, gives an attacker routed access to your entire home LAN over Tailscale. Treat it accordingly:
- Keep it minimal: no extra packages, no services beyond Tailscale
- Keep it updated:
apt upgraderegularly - SSH key auth only, root login disabled
- Static IP outside your DHCP pool so its address never changes unexpectedly
- No inbound ports open from the LAN side — Tailscale initiates outbound connections only
1. Download a Container Template¶
In the Proxmox web UI:
- Click your local storage → CT Templates → Templates
- Download Debian 12
2. Create the LXC¶
In the Proxmox web UI click Create CT:
General
- CT ID: e.g. 100
- Hostname: tailscale-router
- Leave Unprivileged container checked
- Set a root password
Template - Select the Debian 12 template
Disks
- Disk size: 2 GB
CPU
- Cores: 1
Memory
- Memory: 256 MB
- Swap: 256 MB
Network
- Bridge: vmbr0
- IPv4: Static
- IPv4/CIDR: e.g. 192.168.0.2/24 (choose an IP outside your DHCP pool)
- Gateway: your router IP, e.g. 192.168.0.1
DNS - Leave as-is or set to your router IP
Why a static IP?
A static IP assigned in the container itself (not a DHCP reservation) ensures the subnet router's LAN address never changes, even across reboots or DHCP server restarts. This matters because if the container's IP shifts, the Tailscale subnet advertisement still points at the old address until manually corrected.
Click Finish — do not check "Start after created" yet.
3. Add TUN Device Access (Unprivileged LXC)¶
On the Proxmox host shell, verify the TUN device exists:
ls -la /dev/net/tun
If it shows crw-rw-rw- you're good. If not, create it:
mkdir -p /dev/net
mknod /dev/net/tun c 10 200
chmod 0666 /dev/net/tun
Edit the LXC config (replace 100 with your CT ID):
nano /etc/pve/lxc/100.conf
Add at the bottom:
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
Save and exit, then start the LXC.
4. Update and Install Prerequisites¶
Open the LXC console in Proxmox or SSH in as root:
apt update && apt upgrade -y
apt install -y curl sudo
5. Create a Sudo User¶
useradd -m -s /bin/bash jake
passwd jake
usermod -aG sudo jake
Set up the SSH key directory:
mkdir -p /home/jake/.ssh
chmod 700 /home/jake/.ssh
touch /home/jake/.ssh/authorized_keys
chmod 600 /home/jake/.ssh/authorized_keys
chown -R jake:jake /home/jake/.ssh
6. Upload Your SSH Public Key¶
From your local machine:
ssh-copy-id jake@192.168.0.2
Or paste your public key manually:
nano /home/jake/.ssh/authorized_keys
Verify SSH access works before continuing:
ssh jake@192.168.0.2
sudo whoami # should return: root
7. Disable Root SSH Login¶
Do this after confirming jake can SSH in and sudo successfully
If you lock out root before verifying key-based access works, you can end up locked out of the container entirely. Confirm in a second terminal first.
sudo nano /etc/ssh/sshd_config
Find or add (use Ctrl+W to search):
PermitRootLogin no
Restart SSH:
sudo systemctl restart sshd
Disabling root login means an attacker who obtains the root password (e.g. from the Proxmox console) still can't SSH in remotely. Combined with key-only auth (PasswordAuthentication no is also worth adding), SSH access requires possession of your private key.
8. Install Tailscale¶
curl -fsSL https://tailscale.com/install.sh | sh
Enable IP forwarding — required for the container to route packets on behalf of tailnet clients:
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.d/99-tailscale.conf
sysctl -p /etc/sysctl.d/99-tailscale.conf
9. Start Tailscale as Subnet Router¶
sudo tailscale up --operator=jake --advertise-routes=192.168.0.0/24 --accept-dns=false
Replace 192.168.0.0/24 with your actual LAN subnet if different.
--operator=jake allows jake to run tailscale CLI commands without sudo. The tailscaled daemon itself still runs as root.
--accept-dns=false prevents Tailscale from overriding the container's DNS with MagicDNS — this container doesn't need MagicDNS and accepting it can interfere with its role as a router.
This will print an authentication URL — open it in a browser to authorize the machine in your Tailscale account.
10. Approve the Subnet Route¶
In the Tailscale admin console at login.tailscale.com/admin/machines:
- Find
tailscale-router - Click the three-dot menu → Edit route settings
- Enable
192.168.0.0/24
Why manual approval?
Tailscale requires an admin to explicitly approve advertised subnet routes in the console. This is a deliberate security control — a compromised node can't unilaterally gain routed access to your network just by advertising a route.
11. Test Remote Access¶
From a device on an external network with Tailscale running:
Ping the Proxmox host:
ping 192.168.0.x # your Proxmox host's LAN IP
Open the Proxmox web UI:
https://192.168.0.x:8006
If both work, your subnet router is functioning correctly and your full home LAN is accessible over Tailscale.
Notes¶
-
Proxmox host static IP: The Proxmox host has a static IP set at the OS level (
/etc/network/interfaces) — it is not a DHCP client, which is why it doesn't appear in your router's DHCP reservation list. This is fine and more reliable than a DHCP reservation. -
Routing conflict: If a remote network you connect from also uses
192.168.0.x, there will be a routing conflict and LAN access over the subnet router will break silently. In that case, consider also installing Tailscale on the Proxmox host itself so you can reach it via its stable100.x.x.xTailscale IP regardless of the remote network. -
Scope creep: Resist the temptation to run additional services on this container. Its sole job is to route traffic — every additional package or service is an additional attack surface on the container that has LAN-wide reach.