SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

How to Run Tailscale Subnet Router for VPS

Make your VPS advertise private IP ranges to your tailnet. Approve the route, enable reboot-safe IP forwarding, then use --accept-routes on Linux.

Wetin Tailscale subnet router dey do

Tailscale subnet router na one machine wey dey advertise complete range of private IP addresses to your tailnet, so every device for the tailnet fit reach addresses for that range even when no Tailscale dey run there. Your tailnet na your private Tailscale network: na all the devices wey sign in to one account or organisation. Exit node na the feature wey people dey confuse with am, and e dey do opposite work. E dey send all traffic from one device go through the VPS, so the VPS become that device route to public internet.

One sentence for each. Subnet router dey make one private network reachable from the tailnet. Exit node dey change where your public traffic dey comot from. If na the second one you want, read how to run Tailscale exit node for VPS instead. Dem na separate flags, and one VPS fit do both at once, but dem dey solve different problems and dem dey fail for different ways.

When VPS need be subnet router

The common case na private network wey your provider don give you already. Your VPS get public address and second interface for private segment, while the other servers for that segment no get public address at all: database for 10.0.0.20, backup target for 10.0.0.30. Put Tailscale for one VPS, advertise 10.0.0.0/24, and your laptop go reach those private addresses directly. Nothing else for the segment go change, and the database still no get public address.

The other case na network wey dey the other side of the VPS. E fit be home or office LAN (local area network) behind its own router, or rack of appliances wey no fit run Tailscale at all, like managed switch or old NAS with locked firmware. One Linux box for that network go become subnet router for everything else wey dey there.

Both cases get one requirement. The subnet router must already fit reach the range wey e advertise, using its own routing table and its own firewall. Tailscale no dey build that connection. E dey carry traffic go the router, then hand am over to the kernel make e forward am.

Install Tailscale and first check local route

curl -fsSL https://tailscale.com/install.sh | sh

The script dey detect the distribution, add Tailscale package repository, install the tailscale command and tailscaled daemon, then enable the service. Confirm am with systemctl is-active tailscaled; e suppose print active.

Before you do anything else, prove say the VPS fit reach the network wey you plan to advertise.

ip route show
ping -c3 10.0.0.20

ip route show suppose list the private range for real interface, something like 10.0.0.0/24 dev enp7s0 proto kernel scope link src 10.0.0.5. If ping fail here, for the router itself, no Tailscale flag go fix am. The problem dey for VPS network configuration or firewall for the target host. Fix that one first, because every test wey come later depend on am.

Turn on IP forwarding, and make e survive reboot

Linux machine dey drop any packet wey no address to itself unless forwarding dey on. Forwarding packets from other machines na the whole work of subnet router, so you no fit skip this step.

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

Check am with sysctl net.ipv4.ip_forward, wey suppose print net.ipv4.ip_forward = 1.

People dey often do this step halfway. sudo sysctl -w net.ipv4.ip_forward=1 go work immediately but e go disappear for the next boot, so subnet router fit run for weeks and then stop the morning after kernel upgrade reboot. The confusing part be say nothing go look broken. tailscale status still dey show the node online, admin console still dey show say dem approve the route, and clients still get the route installed. Packets dey arrive for the VPS, but kernel dey drop dem without logging anything. Writing the values inside /etc/sysctl.d/99-tailscale.conf na wetin make dem come back after reboot.

If you advertise routes while forwarding still dey off, tailscale up go warn you at that time, with line wey dey close to Warning: IPv4 forwarding is disabled. Subnet routes and exit nodes may not work correctly. Read the output of that command instead of scrolling past it.

sudo tailscale up --advertise-routes=10.0.0.0/24

For VPS wey don already sign in to your tailnet, change the setting directly instead:

sudo tailscale set --advertise-routes=10.0.0.0/24

Use tailscale set for every later change. If you run tailscale up again with only one flag, e go reset the flags wey you no repeat, and the CLI go stop you with an error say changing settings this way requires you to mention all non-default flags. tailscale set changes one setting and leaves the others as dem be.

You fit put several ranges inside one comma-separated list without spaces: --advertise-routes=10.0.0.0/24,192.168.50.0/24. Every entry must be network address for CIDR notation (classless inter-domain routing, the 10.0.0.0/24 form). If you mistakenly write your own host address, 10.0.0.5/24, the command go reject am because the bits after the prefix no be zero, and the error go name the prefix wey you probably mean. To stop advertising, set an empty list with sudo tailscale set --advertise-routes=.

Approve route for admin console

To advertise route na request, e no be change. Until admin approve am, no client go receive the route, and nothing for that range go dey reachable. Na intentional thing be this, because machine wey fit add itself to everybody routing table fit capture traffic for any range wey e like.

Approve am for Machines page of admin console. VPS go show with subnet badge. Open the row, find subnets section, edit route settings, tick the route, then save.

Approval dey apply to each prefix. If you advertise 10.0.0.0/24 today and 192.168.50.0/24 next month, the new prefix go arrive unapproved, while the old one continue to work. Approved route and ignored route look the same from VPS side, so check console before you debug anything else.

You fit skip the manual step with autoApprovers block for tailnet policy file:

{
  "autoApprovers": {
    "routes": {
      "10.0.0.0/24": ["tag:subnet-router"]
    }
  }
}

Then bring the node up with that tag, sudo tailscale up --advertise-routes=10.0.0.0/24 --advertise-tags=tag:subnet-router, and the route go get approval immediately when dem advertise am. The tag must already dey for tagOwners section of the same policy file. E make sense to set this up if you dey rebuild the VPS from script, because rebuilt node na new node, and its routes go start unapproved again.

Why Linux clients dey ignore route without --accept-routes

The route don advertise and approve. Your phone and Mac fit reach 10.0.0.20. Your Linux laptop no fit, and nothing for admin console show say problem dey.

To accept subnet route mean say you write entries inside the client routing table. For Android, iOS, macOS, tvOS and Windows, Tailscale client dey do this for you. For Linux, e no dey do am because Linux machine often dey serve as server or router wey person configure the routing table for a particular reason. If e silently insert a /24 wey e learn from network, e fit break traffic wey that machine dey already handle. So for Linux, you must opt in for each client:

sudo tailscale set --accept-routes

Then check where the route enter:

ip route show table 52
ip route get 10.0.0.20

Tailscale for Linux no dey put accepted routes inside main routing table. E dey put dem for routing table 52 and install policy rules. You fit see the rules with ip rule show for priority range 5210 to 5270. The rules send packets wey no match anywhere go that table. So ip route show by itself no go ever list 10.0.0.0/24, and person wey check only that command fit conclude say --accept-routes no do anything. ip route show table 52 na the command wey show the real state, and e suppose list the advertised range on tailscale0.

One exception dey important to know. If this Linux node na itself a second subnet router for its own local network, --accept-routes go make am send traffic for its own directly connected subnet through the other router instead of through its own interface. For standby router inside high availability pair, leave --accept-routes off and advertise only.

Failure mode: two routers advertising overlapping ranges

Two subnet routers no suppose advertise identical ranges. Overlapping ranges with different prefix lengths dey allowed, and Tailscale go pick the most specific match. If router A dey advertise 10.0.0.0/24 and router B dey advertise 10.0.0.0/16, traffic to 10.0.0.20 go A.

The thing wey dey surprise people na wetin happen when A go offline. Tailscale no go fall back to the less specific route. Traffic to 10.0.0.20 go stop, while traffic to 10.1.0.20 still dey work through B. The symptom go look like say half of the private network don go down. The cause na one offline node wey still get the more specific prefix. If you want failover, make the wider router advertise the narrower prefixes too, so both routers cover the same addresses.

The other overlap dey closer to the client. If you dey use hotel network for 192.168.1.0/24 while your subnet router dey advertise 192.168.1.0/24, both routes go compete for the same destinations. Which one go win depend on the platform. For Linux, install one rule ahead of Tailscale own, so local addresses go use the main table:

sudo ip rule add to 192.168.1.0/24 priority 2500 lookup main

That rule no persistent, and e go disappear for the next boot. The real fix na to choose private range wey you no go meet for other networks. 192.168.0.0/24 and 192.168.1.0/24 na the default ranges for most home routers, so pick something inside 10.0.0.0/8 wey you choose deliberately. The same collision go break plain WireGuard VPN wey you configure by hand, for the same reason: the more specific local route go win, so the traffic no go enter the tunnel.

Failure mode: DNS resolve to address wey no route cover

This one hard to debug, because nothing dey report error. The name resolve. The connection time out.

Make we say db.internal.example.com resolve to 10.0.5.20 through your private nameserver, and you advertise 10.0.0.0/24. The lookup succeed, because DNS (domain name system) resolution and IP routing na separate steps, and neither one dey check the other. Then packet wey go 10.0.5.20 no find matching route for the tailnet, so e comot through the client default gateway and disappear.

Two commands go separate the two parts:

nslookup db.internal.example.com
ip route get 10.0.5.20

If the lookup return address but ip route get no answer with dev tailscale0, the name dey correct and route dey missing. Advertise range wey cover the address, either 10.0.0.0/16 or another explicit prefix, then approve the new prefix for the console.

This same trap fit happen for the nameserver itself. If you set global nameserver for the admin console with private address like 10.0.0.53, that address must dey inside approved route, or your devices no go reach the resolver at all. If you turn on the option wey override local DNS servers while you point to resolver wey nobody fit reach, every device for the tailnet go lose name resolution at once, including the ones wey work one second before. Advertise and approve route to the resolver first, then change the DNS setting. If DNS inside tunnel na the part wey you dey struggle with, the way DNS dey break over WireGuard tunnel explain the same mechanism without the coordination layer on top.

By default, subnet router dey rewrite source address of every forwarded packet to its own private address. Na SNAT (source network address translation), and e dey make replies work without changing anything for private network: database for 10.0.0.20 go answer the VPS, wey e already know how to reach. The disadvantage be say database go see every tailnet connection like say e come from VPS, so per-source firewall rules and access logs no go tell you anything.

Turn am off for Linux when you want make client real tailnet address remain:

sudo tailscale set --snat-subnet-routes=false

Hosts for private network then need route back to 100.64.0.0/10, the range wey Tailscale dey assign to devices, and the route must point to subnet router. Without that return route, their replies go the default gateway and dem no go ever arrive, so connections go hang after the first packet. Add static route for private network gateway, or leave SNAT on.

Site-to-site link na when two subnet routers dey do this at the same time. Each one advertises its own network and accepts the other router network:

sudo tailscale up --advertise-routes=10.0.0.0/24 --snat-subnet-routes=false --accept-routes

Run the matching command for the other router with its own range. The two ranges must different. If large transfers dey stall while ssh and ping dey work fine, the cause na MSS (maximum segment size), wey be the largest data chunk wey TCP packet fit carry. Tunnel overhead makes forwarded packets too large for some link along the path, and clamping fixes am:

sudo iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Save that rule with iptables-persistent, or e go disappear at the next boot.

Housekeeping wey go keep am running

Node keys dey expire after 180 days by default, as of August 2026. When key for subnet router expire, the node go sign out and the whole advertised range go become unreachable, without any configuration change wey fit explain am. Disable key expiry for this machine for the Machines page of the admin console, then write down say you do am.

Tailscale prefer direct connection between peers and e go fall back to im relay servers when e no fit establish one. The relays dey work, but dem add latency. VPS wey get public address na the easy case: allow inbound UDP 41641 and most peers go connect directly. If ufw dey manage the firewall, the ufw rules wey VPS really need cover the syntax.

Access rules na the other half. For default tailnet, every device wey belong to you fit reach every other one, so approved route go just work. Once you write ACL policy, destination side of the rule must name the private range, because 10.0.0.20 no be tailnet address and rules wey target tailnet IPs or tags no cover am.

Finally, decide whether you want coordination server wey you no dey run. Tailscale control plane na hosted service. Your keys remain for your machines, but the account and policy file dey there. Running Headscale, the self-hosted Tailscale control server go keep am for your own VPS, but you go need maintain am. The other answer to the same concern na to also leave Tailscale clients behind, then self-hosting the NetBird VPN server go put the coordination layer and im own mesh clients for one machine wey you control. If you still dey decide between this model and hand-written config, the comparison of WireGuard and Tailscale explain wetin the coordination layer dey give you and wetin e dey cost.

FAQ

Wetin be difference between subnet router and exit node?

Subnet router dey advertise range of private addresses, so tailnet devices fit reach machines wey no dey run Tailscale. Exit node dey advertise itself as route to the whole internet, so device dey send all its traffic through that node public address. One VPS fit serve as both. Dem be separate flags, --advertise-routes and --advertise-exit-node, and each one need its own approval for admin console.

Why my Linux client dey ignore the advertised subnet route?

Linux clients no dey accept subnet routes unless you tell dem to. Run sudo tailscale set --accept-routes for the client. Then check with ip route show table 52, no be ip route show. Tailscale dey install accepted routes for routing table 52 and reach dem through policy rules, so main table no go list dem and working route fit look like say e missing.

My subnet stop working after reboot. Wetin spoil?

Na IP forwarding most likely. Value wey you set with sysctl -w no dey survive reboot, so write am to /etc/sysctl.d/99-tailscale.conf and confirm with sysctl net.ipv4.ip_forward. If forwarding dey on and the range still no reachable, check the node for admin console. Node keys dey expire after 180 days by default, and expired subnet router dey look like network fault instead of account problem.

Two subnet routers fit advertise the same range?

No be identical ranges. Overlapping ranges with different prefix lengths dey okay, and the most specific one dey win. Failover need care: when router wey hold the more specific prefix go offline, Tailscale no go fall back to the wider route, so that traffic go stop. For real standby pair, make both routers advertise the same specific prefixes.

The hostname dey resolve but connection dey time out. Why?

DNS resolution and routing na separate steps. Name fit resolve to address wey no approved route cover, and packet go then leave through client default gateway. Run ip route get <address> for the client. If the answer no include dev tailscale0, advertise range wey cover that address and approve the new prefix for admin console.