Tailscale
Tailscale puts all your devices on one private network that works from anywhere, with no ports opened and no VPN server to run.
At a glance#
Tailscale has two halves. A coordination server that Tailscale runs tells each of your devices who the others are and which keys to trust. Your devices then send traffic straight to each other over WireGuard, encrypted end to end.
The dashed lines carry only keys and rules. The solid lines carry your traffic, and they never pass through Tailscale's servers unless a direct path is impossible, in which case a DERP relay forwards the packets it cannot read.
The problem it solves#
You want to reach a machine that is not on your local network: your n8n box, a home PC, a GPU server running an agent. The usual ways either expose that machine to the whole internet or route everything through one server you have to run.
| Approach | What you expose | Path your traffic takes | Setup and upkeep | Who can get in |
|---|---|---|---|---|
| Port forwarding on your router | A public port on your home IP, open to anyone who scans it | Straight in, if your ISP allows it (many mobile and CGNAT ISPs do not) | Router rules, dynamic DNS, TLS certs, patching | Anyone who finds the port and gets past the login |
| Classic VPN server (OpenVPN, a WireGuard hub) | One public VPN port | Every packet goes through the VPN server, even between two devices in the same city | Run and patch the server, hand out configs and keys by hand | Anyone holding a valid config file |
| Tailscale | Nothing: devices only make outbound connections | Device to device, directly where possible | Install the app, sign in | Only devices signed in to your tailnet, and only where your policy allows |
The last column is the real shift. Old VPNs trust whoever is "inside". Tailscale ties every device to a signed-in identity and checks a policy for every connection, which is what people mean by zero trust networking.
How a connection is made#
Tailscale is WireGuard plus the hard parts WireGuard leaves to you: handing out keys, finding each device, and getting through routers. The coordination server does the first two; your devices do the third themselves.
Tailscale says more than nine in ten connections end up direct (NAT traversal improvements, October 2025). Because step 4 happens before the direct path is found, you never wait for hole punching: the first packets already flow through the relay.
The three keys on every device
| Key | Made when | What it does | Leaves the device? |
|---|---|---|---|
| Machine key | The app is installed | Proves to the coordination server which physical machine this is | Only the public half |
| Node key | Each sign-in | The WireGuard key other devices use to encrypt traffic to you; it expires (default 180 days) and is revoked the moment you remove the device | Only the public half |
| Disco key | With the node key | Encrypts the small discovery messages (ping, pong, "call me maybe") devices use to find a path | Only the public half |
Private keys never leave your device, so the coordination server could not decrypt your traffic even if it wanted to. It is "a shared drop box for public keys", in Tailscale's own words (How Tailscale works).
Inside the tunnel. Traffic uses WireGuard: Curve25519 key exchange, ChaCha20-Poly1305 encryption, a fresh session key every 2 minutes. Tailscale ships its own tuned userspace WireGuard (wireguard-go), which in its tests outran the Linux kernel module: 13.0 Gb/s against 11.8 Gb/s on one bare-metal box (more throughput, April 2023).
If the coordination server goes down, connections you already have keep working on the keys and rules each device cached. New devices, new keys and policy changes wait until it is back (control and data planes).
Direct or relayed#
A connection is direct unless both ends sit behind "hard" routers. Then traffic goes through a relay, which is slower but still encrypted end to end.
Why direct sometimes fails. Most home routers use "easy" NAT: your device keeps the same public port whoever it talks to, so the other side can aim at it. A "hard" (symmetric) NAT picks a new port for every destination, so the other side has nothing to aim at. Cloud NAT gateways (AWS, for example) and some corporate and mobile networks behave this way. One hard side can often still be punched; two cannot.
| Your side | Other side | Result |
|---|---|---|
| No NAT (public IP) | Anything | Direct |
| Easy NAT | Easy NAT | Direct |
| Easy NAT | Hard NAT | Usually relayed |
| Hard NAT | Hard NAT | Relayed |
| UDP blocked by a firewall | Anything | Relayed through DERP on port 443 |
Source: device connectivity and connection types. Tailscale's blog puts the odds of punching through two hard NATs at about 0.01% in 20 seconds (How NAT traversal works).
DERP (Designated Encrypted Relay for Packets) has two jobs: it carries the setup messages that let devices find each other, and it relays traffic when nothing else works. It runs over HTTPS on port 443, so it gets through almost any firewall. It forwards packets by public key and cannot decrypt them. Each device picks the nearest region as its "home DERP" (DERP servers).
Peer relays let one of your own machines with a reachable UDP port do the relaying instead, so you skip Tailscale's shared relays. They went generally available on all plans, the free one included, on February 18, 2026 (Peer Relays GA). In Tailscale's example a path through the Los Angeles DERP took about 40 ms against 3 to 5 ms through a peer relay. Turn one on with tailscale set --relay-server-port=40000 on a box with that UDP port open, then allow it in your policy with the tailscale.com/cap/relay capability. Client and relay both need version 1.86 or later.
How to tell which path you are on
tailscale status # each peer shows: direct 1.2.3.4:41641, relay "lhr", or peer-relay
tailscale ping my-server # shows "via DERP(lhr)" first, then "via 1.2.3.4:41641" once direct
tailscale netcheck # UDP: true/false; MappingVariesByDestIP: true means you are behind a hard NAT
To get more direct connections: turn on UPnP or NAT-PMP on your router, open UDP 41641 inbound on servers, give cloud servers a public IP instead of a NAT gateway, or add a peer relay.
Tailnets, addresses and MagicDNS#
Your tailnet is your private network: every device you sign in, with a fixed address and a name. Each device gets an address in the 100.x range that never changes, wherever the device goes.
| Thing | What it looks like | Notes |
|---|---|---|
| Tailnet | Everything signed in under your account or organization | One per sign-up; Enterprise can run several |
| Tailnet DNS name | tail1a2b3c.ts.net, or a "fun name" like cat-crocodile.ts.net | Pick a fun name under DNS settings, Rename tailnet (tailnet name) |
| IPv4 address | 100.101.102.x, from 100.64.0.0/10 | That range is reserved for carrier-grade NAT, so it rarely clashes with home (192.168.x) or office (10.x) networks |
| IPv6 address | fd7a:115c:a1e0::... | Private IPv6 range; works even if your ISP has no IPv6 |
| MagicDNS name | n8n-box or n8n-box.tail1a2b3c.ts.net | The device's name, so ssh n8n-box just works; on by default since October 2022 |
| Quad100 | 100.100.100.100 | A resolver that lives on each device and answers MagicDNS lookups locally; it never crosses the network |
| HTTPS certificate | https://n8n-box.tail1a2b3c.ts.net | tailscale cert gets a real Let's Encrypt cert; the private key stays on the device |
Addresses change only if you remove and re-add the device, reset it, or an admin changes it by hand (IP addresses).
Split DNS sends lookups for one domain to a chosen server: for example, corp.internal to your office DNS server, everything else to normal DNS (DNS). Turn MagicDNS off on one device with tailscale set --accept-dns=false.
One privacy catch with HTTPS certs. Every certificate is logged in public Certificate Transparency logs, so the machine name and tailnet name become public. Do not turn on HTTPS if a machine name gives something away (HTTPS certificates). Certificates last 90 days; Serve and Caddy renew them for you.
Who can reach what: ACLs, grants and tags#
A brand-new tailnet lets every device reach every other device. The moment you add a second person or a server you do not fully trust, you replace that with a policy file, and from then on anything the policy does not allow is blocked.
The policy lives in the admin console under Access controls, written in HuJSON (JSON that allows comments and trailing commas). The coordination server turns it into firewall rules and pushes each device only the rules and keys it needs; each device then drops disallowed packets itself. A device you are not allowed to reach is not even in your device list.
Grants or ACLs? Grants are the newer syntax and what Tailscale recommends for every new tailnet. Old acls rules still work and can sit in the same file while you migrate, but new features only come to grants (grants vs ACLs).
| Building block | What it is | Example |
|---|---|---|
| User | A person, by their sign-in email | musaib@example.com |
| Group | A named list of users | group:admins |
| Tag | An identity for a machine, not a person; a tagged server keeps working if the person who added it leaves | tag:server, tag:ci |
| tagOwners | Who may put a tag on a device; a tag must be listed here before use | "tag:server": ["group:admins"] |
| Autogroup | Built-in sets Tailscale keeps up to date | autogroup:member (everyone in the tailnet), autogroup:self (your own devices), autogroup:internet (via an exit node) |
| Host | A friendly name for an IP or subnet | "home-lan": "192.168.1.0/24" |
| Grant | Who (src) may reach what (dst) on which ports (ip), optionally through a router (via) | see below |
| SSH rule | Who may SSH as which user, and whether to re-check their login | see below |
| Test | A check that runs on every save; a failing test blocks the change | "accept": ["tag:server:22"] |
A worked policy for a setup like yours: you are the admin, a server runs n8n, a box runs AI agents, GitHub Actions deploys, and one machine is an exit node.
{
// People
"groups": { "group:admins": ["you@example.com"] },
// Who may tag machines
"tagOwners": {
"tag:server": ["group:admins"],
"tag:agent": ["group:admins"],
"tag:ci": ["group:admins"],
"tag:exit": ["group:admins"],
},
"grants": [
// Everyone reaches their own devices
{ "src": ["autogroup:member"], "dst": ["autogroup:self"], "ip": ["*"] },
// Admins reach every tagged machine on any port
{ "src": ["group:admins"], "dst": ["tag:server", "tag:agent"], "ip": ["*"] },
// AI agents may call n8n (port 5678) and nothing else on the server
{ "src": ["tag:agent"], "dst": ["tag:server"], "ip": ["tcp:5678"] },
// CI may only SSH in to deploy
{ "src": ["tag:ci"], "dst": ["tag:server"], "ip": ["tcp:22"] },
// Members may browse the internet through the exit node
{ "src": ["autogroup:member"], "dst": ["autogroup:internet"], "via": ["tag:exit"], "ip": ["*"] },
],
// Tailscale SSH: admins log in to tagged boxes, re-confirming sign-in every 12 hours
"ssh": [
{ "action": "check", "src": ["group:admins"], "dst": ["tag:server", "tag:agent"], "users": ["autogroup:nonroot", "root"] },
{ "action": "accept", "src": ["tag:ci"], "dst": ["tag:server"], "users": ["deploy"] },
],
// Saved only if these hold
"tests": [
{ "src": "tag:agent", "accept": ["tag:server:5678"], "deny": ["tag:server:22"] },
],
}
What this policy allows, at a glance:
| From | Own devices | tag:server | tag:agent | Internet via exit node |
|---|---|---|---|---|
| You (group:admins) | All ports | All ports, SSH with re-check | All ports, SSH with re-check | Yes |
| tag:agent (AI agent box) | No | Port 5678 only | No | No |
| tag:ci (GitHub runner) | No | SSH as deploy only | No | No |
| Anyone else you add | All ports | No | No | Yes |
Good habits. Tag every server rather than leaving it under your personal account; tagged devices also have key expiry off by default. Write a test for each rule you care about. If you change the policy from the console and from Terraform or GitOps, the file wins, so pick one place.
Routing traffic: exit nodes, subnet routers, app connectors#
Normally only traffic to other tailnet devices goes through Tailscale. Three features let one device carry traffic further: all of your internet browsing, a whole LAN, or just a few domains.
| Feature | Use it when | Set up on the router device | Then |
|---|---|---|---|
| Exit node | You want a home IP while travelling, or safe browsing on cafe Wi-Fi | Turn on IP forwarding (Linux), then sudo tailscale set --advertise-exit-node | Approve it in the console (Machines, Edit route settings); on the client tailscale set --exit-node=home-pc; stop with tailscale set --exit-node= |
| Mullvad exit nodes | You want exits in many countries without running servers | Nothing: buy the add-on ($5 a month per 5 devices, beta) | tailscale exit-node list, then pick one |
| Subnet router | You need devices that cannot run Tailscale: a printer, NAS, camera, an office LAN, a cloud VPC | IP forwarding, then sudo tailscale set --advertise-routes=192.168.1.0/24 | Approve the routes; Linux clients run sudo tailscale set --accept-routes |
| App connector | A SaaS tool only accepts logins from allowlisted IPs | A Linux box with a public IP and forwarding, given a tag | List the domains for that tag in the console; traffic to those domains leaves from that box's IP |
| Tailscale Services | You want a stable name like svc:n8n that can move between hosts or run on several | Define the service in the console; on each tagged host tailscale serve --service=svc:n8n --https=443 127.0.0.1:5678 | Grant access with "dst": ["svc:n8n"] |
IP forwarding on Linux, needed for exit nodes and subnet routers:
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
Three things trip people up. If you write your own policy, exit traffic is blocked until you add a grant to autogroup:internet (the worked policy above has one). Exit nodes on macOS, Windows and Android are slower because they route in userspace; a Linux box makes the best exit node. And a subnet router hides your real address behind its own by default (SNAT), which is usually what you want. MagicRoute, in beta since October 19, 2026, picks automatically between several redundant routers, exit nodes or connectors.
Tailscale SSH#
Tailscale SSH lets you log in to a server with no SSH keys at all: your Tailscale sign-in is the key, and the policy file decides who may log in as which user.
| Ordinary SSH | Tailscale SSH | |
|---|---|---|
| How you prove who you are | A private key file on your laptop, its public half in ~/.ssh/authorized_keys on every server | Your Tailscale identity (Google, GitHub, etc.); nothing to copy around |
| Port 22 exposed | Usually to the whole internet | Only inside the tailnet; the Tailscale daemon answers it |
| Removing someone | Hunt down their key on every server | Remove them from the tailnet or the policy; it applies everywhere at once |
| Extra login check | None by default | check mode makes you re-confirm your sign-in (and MFA) every 12 hours by default |
| Session recording | Separate tooling | Was built in; now moving to the paid Tailscale PAM extension (old recorder support ends August 2027) |
Turn it on
# on the server (Linux, or macOS with the open-source tailscaled)
sudo tailscale set --ssh
# from your laptop: plain ssh, by MagicDNS name
ssh root@n8n-box
You also need an ssh rule in the policy file (see the worked policy above) and a grant that lets you reach port 22. accept lets you straight in; check sends you to your identity provider first, from 1 minute up to 168 hours between checks. Synology and QNAP cannot be Tailscale SSH servers (Tailscale SSH).
Plans. The SSH docs say all plans; the pricing page lists "Basic Tailscale SSH, up to 5 hosts" on Standard and "Advanced Tailscale SSH" (such as custom check periods) on Premium. Free Personal tailnets can use it.
Why it matters for agents. A coding agent on a remote box (Claude Code, Codex, Hermes) is reached the same way: ssh agent-box, then run it inside tmux so it keeps going when you close the laptop. The setups section below walks through it.
Serve and Funnel#
Serve puts a local app on a private HTTPS address only your tailnet can open; Funnel puts the same address on the public internet. Both give you a real certificate with no reverse proxy, no open router port and no domain to buy.
| Serve | Funnel | |
|---|---|---|
| Who can open it | Tailnet devices your policy allows | Anyone with the URL |
| Address | https://<device>.<tailnet>.ts.net | The same, resolvable on public DNS (can take up to 10 minutes) |
| Ports | Any | 443, 8443 or 10000 only |
| Protocols | HTTPS, HTTP, raw TCP, TLS-terminated TCP | TLS only |
| Status and plans | All plans | Beta, all plans, client 1.38.3 or later, bandwidth capped (limits not published) |
| Needs | MagicDNS and HTTPS certificates on | The same, plus the funnel attribute in the policy (the first run walks you through it) |
| Good for | Private dashboards, n8n editor, Jupyter, a model server for your agents | Webhooks from Stripe, GitHub or WhatsApp, a demo for a client, a short-lived share |
Commands
tailscale serve 5678 # private HTTPS -> localhost:5678 (stays in the foreground)
tailscale serve --bg 5678 # same, kept running across reboots
tailscale serve --bg --set-path=/api 8000 # mount another app under /api
tailscale serve status # what is being served
tailscale serve --https=443 off # stop it
tailscale funnel --bg 5678 # public HTTPS -> localhost:5678
tailscale funnel status
tailscale funnel --https=443 off
A port is either served or funnelled: whichever command ran last wins (Funnel, serve CLI). Funnel traffic is still encrypted to your device: Tailscale's relay passes the TLS stream through without decrypting it. But the app itself is now public, so it needs its own login.
Taildrop, sharing and the other features#
Beyond connecting devices, Tailscale has a toolbox of smaller features. The ones worth knowing, with how to use each:
| Feature | What it does | How you use it | Status |
|---|---|---|---|
| Taildrop | Send files between your own devices, like AirDrop across any OS | tailscale file cp report.pdf my-phone: (note the colon); receive with sudo tailscale file get . | Alpha; your own devices only |
| Device sharing | Let someone outside your tailnet reach one machine | Machines, Share, by email or link; they cannot connect back to you unless you share too | All plans; link sharing beta |
| Ephemeral nodes | Devices that delete themselves 30 to 60 minutes after going offline | An ephemeral auth key, or tailscaled --state=mem: | All plans; ideal for CI and containers |
| Auth keys | Join a server without a browser login | Keys page, Generate auth key (one-off or reusable, ephemeral, pre-approved, tagged; 1 to 90 days); sudo tailscale up --auth-key=tskey-... | All plans |
| OAuth clients | Long-lived credentials for automation and the API, scoped and tag-bound | Trust credentials page; the secret works as an auth key with --advertise-tags | All plans |
| Workload identity federation | CI jobs and cloud workloads join using their own short-lived OIDC token, so no secret is stored | tailscale up --client-id=... --audience=... --advertise-tags=tag:ci | GA February 2026, all plans |
| tsnet | A Go library that makes your program its own tailnet device | srv := new(tsnet.Server); srv.Hostname = "mybot"; ln, _ := srv.Listen("tcp", ":80") | Open source |
| Kubernetes operator | Expose cluster services to the tailnet, reach tailnet services from pods, proxy the API server | Helm chart tailscale/tailscale-operator | All plans |
| Docker image | Run Tailscale as a sidecar container | tailscale/tailscale with TS_AUTHKEY, TS_STATE_DIR (keep it on a volume or every restart is a new device), TS_SERVE_CONFIG | All plans |
| Userspace networking | Run Tailscale where you cannot create a network device: Heroku, Cloud Run, locked-down containers | tailscaled --tun=userspace-networking --socks5-server=localhost:1055, then point apps at that proxy | All plans |
| Aperture | An AI gateway: agents and apps call model APIs using their tailnet identity instead of shared API keys, with quotas and audit logs | Sold separately; GA August 2026 | Paid extension |
| Logs | Configuration audit logs (who changed what, 90 days) on every plan; network flow logs (who talked to whom, metadata only) on Premium | Logs page, or stream to a SIEM | Varies by plan |
Aperture is the newest piece and the most relevant to AI work: it puts one gateway between your agents and providers like Anthropic or OpenAI, so no agent box ever holds a raw API key (Aperture GA).
Sign-in and trust: who gets in#
Tailscale has no passwords of its own. You sign in with an identity provider you already use, and every device inherits that identity. Four controls then decide whether a device is trusted, each stricter than the last.
| Layer | What it checks | Default | Where to set it |
|---|---|---|---|
| Identity provider | Who you are: Google, Microsoft or Entra ID, GitHub, Apple, Okta, OneLogin, any OIDC provider, or a passkey | Required; there is no email and password sign-up | Chosen when the tailnet is created; MFA is set at the provider, not in Tailscale |
| User approval | A new person must be approved before joining | On for tailnets created since May 22, 2025 | Settings, User management |
| Device approval | Each new device waits for an admin to approve it | Off | Settings, Device management |
| Key expiry | Every device must sign in again after a set time | 180 days (1 to 180 allowed); tagged devices never expire | Settings, Key expiry; per device on the Machines page |
| Tailnet Lock | New devices must be signed by keys you hold, so even Tailscale's servers cannot add one | Off | tailscale lock init on trusted devices |
Key expiry in practice. When a device's key expires it drops off the tailnet until someone signs in on it again with sudo tailscale up --force-reauth. For servers, either tag them (tagged devices skip expiry) or click Disable key expiry on that machine. An admin can also give an expired device 30 extra minutes from the console while you fix it.
Tailnet Lock, step by step#
Normally you trust Tailscale's coordination server to hand out only real public keys. Tailnet Lock removes that trust: each device's key must carry a signature from one of your trusted lock keys, checked by every client. A compromised control plane could no longer slip in a rogue device.
# 1. On each device you want as a signer, print its lock key
tailscale lock status
# 2. On one of them, turn the lock on with up to 20 signer keys
tailscale lock init tlpub:KEY1 tlpub:KEY2
# It prints 10 disablement secrets. Store them offline.
# 3. When a new device joins, sign it from a signer device
tailscale lock sign nodekey:NEWNODE tlpub:SIGNERKEY
The catches: it needs client v1.46.1 or later; Android devices cannot be signers; you cannot use it together with device approval; and if you lose every signer and all 10 disablement secrets, nobody can add devices, Tailscale included. For one person with a handful of machines, device approval plus key expiry is usually enough; Tailnet Lock suits people who must not depend on Tailscale's servers at all (Tailnet Lock docs).
Plans and pricing#
For you alone, Tailscale is free: the Personal plan covers up to 6 users and unlimited personal devices, as long as the use is non-commercial. Wenkraft work counts as commercial, so a business tailnet belongs on Standard at $8 a seat a month. These are the "Pricing v4" plans Tailscale launched on April 8, 2026.
| Plan | Price | Users | Devices | Notable extras |
|---|---|---|---|---|
| Personal | $0, non-commercial only | Up to 6 | Unlimited user devices; 50 tagged resources (servers, connectors), then $1 a month each | 3 ACL groups, 1,000 ephemeral minutes a month |
| Standard (was Starter) | $8 per seat per month | Unlimited | Unlimited user devices | SCIM, device posture, MDM config, advanced user roles, 10 ACL groups |
| Premium | $18 per seat per month | Unlimited | Unlimited user devices | Just-in-time access, advanced Tailscale SSH, network flow logs, log streaming, 300 ACL groups |
| Enterprise | Custom | Custom | Custom | Invoicing, custom contract, custom tailnet subdomains, a solutions engineer |
How billing works. You pay per seat, not per active user, and empty seats still cost money. A seat fills the first time a person logs in to the admin console or signs in a device. Seats added mid-month are prorated.
Add-ons. Mullvad exit nodes (route your traffic out through Mullvad VPN's servers) cost $5 a month for every 5 devices. Aperture, Tailscale's AI gateway, and the PAM, CI/CD, workload and IoT extensions are sold separately through sales.
Features on every plan, the free one included. MagicDNS, Tailscale SSH, Funnel, Serve, Taildrop, exit nodes, subnet routers, Peer Relays (2 free relays) and Tailscale Services all work on Personal.
What changed. The old plans (Pricing v3, April 2023) gave 3 free users and 100 devices, and Starter cost $6 per active user. Personal Plus is gone; its 6-user limit is now the free limit. Older blog posts and comparison sites still quote the v3 numbers.
Headscale: running the control plane yourself#
The Tailscale apps on your devices are open source, but the coordination server is not. Headscale is an independent, open-source (BSD-3) rewrite of that server. You run it on your own box, point the official Tailscale apps at it, and nothing about your network touches Tailscale's company servers. It is not made by Tailscale, though a Tailscale engineer helps maintain it.
| Tailscale (hosted) | Headscale (self-hosted) | |
|---|---|---|
| Cost | Free for personal use; paid per seat for teams | Free; you pay for the server it runs on |
| Who runs it | Tailscale | You: updates, backups, uptime, TLS |
| Tailnets | Many, with an admin console | One per server; managed by CLI, or a third-party web UI such as Headplane |
| Clients | Official apps | The same official apps (v1.80.0 or later), pointed at your server with --login-server |
| MagicDNS, Taildrop, tags, subnet routers, exit nodes | Yes | Yes |
| ACLs and grants | Yes | Yes; grants since 0.29.0 |
| Tailscale SSH, including check mode | Yes | Yes |
| Relays | Global DERP fleet plus peer relays | Embedded DERP server you run, plus peer relays; can also borrow Tailscale's public DERP map |
| Sign-in | Big identity providers, passkeys | OIDC (bring your own), or pre-auth keys |
| Funnel, Serve with HTTPS certs, flow logs, app connectors, Aperture | Yes | No |
| Tailnet Lock | Yes | Not listed as supported |
| Support | Docs, plus vendor support on paid plans | Community only |
The current release is 0.29.x (0.29.7 per the docs in early November 2026). The project says it is not tested behind reverse proxies or in containers, so it runs best as a plain binary with its own TLS.
# On the Headscale server
headscale users create musaib
headscale preauthkeys create --user musaib --expiration 24h
# On each device, use the normal Tailscale app
sudo tailscale up --login-server https://hs.example.com --auth-key <KEY>
Should you use it? Only if self-hosting is the point: privacy, an air-gapped network, or curiosity. For a solo setup, the free hosted Personal plan does more (Funnel, HTTPS Serve, a console) with no server to maintain.
Alternatives compared#
Two questions separate the options: who runs the pieces, and whether devices talk directly (a mesh) or everything goes through a hub or tunnel.
| Option | Model | Protocol | Free tier | Paid from | Self-host | Best at |
|---|---|---|---|---|---|---|
| Tailscale | Managed mesh | WireGuard | 6 users, non-commercial | $8 per seat a month | Control plane via Headscale only | Least setup, best NAT traversal, most features |
| ZeroTier | Managed mesh, layer 2 | Own protocol (Salsa20, Poly1305) | 10 devices, non-commercial | $18 a month (Essential) | Yes, own controller | Virtual LAN: broadcast, games, odd protocols |
| NetBird | Mesh, cloud or self-hosted | WireGuard | 5 users, 100 machines | €6 per user a month | Yes, fully (server AGPL) | Tailscale-like, but you can own everything |
| Cloudflare Tunnel | Outbound tunnel to Cloudflare's edge | QUIC or HTTP/2 | Free; Zero Trust free to 50 users | $7 per user a month | No | Putting a web app on a public domain behind Cloudflare |
| Twingate | Zero-trust connectors | TLS | 5 users | Per user | Connectors only | Team access to private resources, no mesh |
| WireGuard | Point-to-point, manual | WireGuard | Free | Free | Yes, you do everything | Fastest, smallest, if you enjoy key management |
| OpenVPN | Classic hub VPN | TLS (OpenSSL) | Community Edition free; Access Server 2 connections | $7 per connection a month, billed yearly | Yes | Legacy setups and appliances that speak only OpenVPN |
How to choose. Want it working in five minutes across laptops, servers and phones: Tailscale. Must own every server: NetBird self-hosted or Headscale. Need a public website without opening ports: Cloudflare Tunnel, or Tailscale Funnel for something small. Need a true virtual LAN with broadcast traffic: ZeroTier. Two fixed machines and no third party at all: plain WireGuard.
Tailscale and Cloudflare Tunnel are not really rivals. A common pattern is Tailscale for private access to your own machines, and Cloudflare Tunnel for the one service the public needs to reach.
Setups for you#
Five concrete setups that match how you work: self-hosted n8n, home machines, AI and coding agents on remote boxes, Claude Code on a server, and CI. They all live in one free Personal tailnet.
1. Claude Code on a server, from anywhere#
The goal: a long-running Claude Code session on a VPS that you can check from your laptop or phone, with port 22 closed to the internet.
On the server, install and join with SSH on and a tag:
curl -fsSL https://tailscale.com/install.sh | sh, thensudo tailscale up --ssh --advertise-tags=tag:agent.In your policy file, let your own devices SSH in and give the tag nothing else (see the policy below).
Close port 22 in the VPS firewall. Tailscale SSH does not need it.
From your laptop:
tailscale ssh you@agent-box, thentmux new -As claudeand runclaudeinside.Detach with
Ctrl-b d. Later, from any device,tailscale ssh you@agent-boxandtmux attach -t claudeputs you back in the same session. On a phone, any SSH app works once the Tailscale app is on.
2. AI and coding agents on remote boxes, safely#
An agent with shell access is the device you should trust least. Tag every agent box, let people reach it, and do not let it reach anything back:
{
"tagOwners": { "tag:agent": ["autogroup:admin"], "tag:ci": ["autogroup:admin"] },
"grants": [
{ "src": ["autogroup:member"], "dst": ["tag:agent"], "ip": ["*"] },
{ "src": ["tag:ci"], "dst": ["tag:agent"], "ip": ["tcp:22"] }
],
"ssh": [
{ "action": "accept", "src": ["autogroup:member"], "dst": ["tag:agent"], "users": ["autogroup:nonroot", "root"] }
]
}
Because no grant lists tag:agent as a source, a compromised or confused agent cannot open your home machine or n8n, even though they share the tailnet. The agent can still use the internet for model APIs and package installs. If you want agents to call model APIs without holding raw API keys, that is what Aperture is for.
3. Your self-hosted n8n#
Your n8n runs on Heroku. Heroku dynos cannot create a network device and restart daily with a fresh disk, so Tailscale there only works in userspace mode, with an ephemeral or OAuth key and no saved state. That is enough for n8n to call private things through Tailscale's proxy: start tailscaled --tun=userspace-networking --outbound-http-proxy-listen=localhost:1055 in the dyno, and point n8n's HTTP Request node, or HTTP_PROXY, at http://localhost:1055.
The cleaner setup is a small VPS with n8n and the Tailscale container side by side:
Run
tailscale/tailscaleas a sidecar withTS_AUTHKEY,TS_HOSTNAME=n8nandTS_STATE_DIRon a volume, sharing the network with the n8n container.Serve the editor privately:
tailscale serve --bg 5678. The editor is now athttps://n8n.<your-tailnet>.ts.netfor your devices only, with a valid HTTPS certificate.Expose only the webhook path publicly:
tailscale funnel --bg --set-path=/webhook http://localhost:5678/webhook. Test it once from a phone on mobile data.Set n8n's
WEBHOOK_URLto the public Funnel address so the webhook URLs it shows are correct.
The editor login page is then never on the public internet, which removes the main way self-hosted n8n instances get attacked.
4. Home machines#
Install Tailscale on the home PC or a small always-on box such as a Raspberry Pi.
To reach the whole home network (printer, NAS, router page):
sudo tailscale up --advertise-routes=192.168.1.0/24, then approve the route on the Machines page.To browse through your home connection when travelling: add
--advertise-exit-node, approve it, and pick it from the Tailscale menu on your laptop.Turn off key expiry for that machine so it never drops off while you are away.
5. CI that reaches your servers#
GitHub Actions can join the tailnet for one run and vanish afterwards, with no stored secret, using workload identity federation:
permissions:
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: tailscale/github-action@v4
with:
oauth-client-id: ${{ secrets.TS_CLIENT_ID }}
audience: ${{ secrets.TS_AUDIENCE }}
tags: tag:ci
- run: ssh deploy@agent-box ./deploy.sh
Create the federated identity under Trust credentials in the admin console first, scoped to tag:ci and to your repository. The runner appears as an ephemeral device and is removed soon after the job ends; the grant above lets it reach only port 22 on agent boxes.
Setting it up, step by step#
From nothing to a working tailnet takes about ten minutes. Do the steps in this order.
| Step | Where | What to do |
|---|---|---|
| 1. Create the tailnet | login.tailscale.com | Sign in with Google, GitHub, Microsoft or Apple. The account you pick owns the tailnet, so use the one you will keep. |
| 2. Add your laptop | Mac App Store, Windows installer, or the Linux script | Install, sign in with the same account. It gets a 100.x address and a name. |
| 3. Add your phone | App Store or Play Store | Same sign-in. Now the laptop and phone can reach each other. |
| 4. Add a server | SSH into it | Run the Linux commands below, using an auth key so no browser is needed. |
| 5. Turn on MagicDNS and HTTPS | Admin console, DNS page | MagicDNS is on by default for new tailnets; enable HTTPS certificates if you plan to use Serve. |
| 6. Write your access policy | Admin console, Access controls | Replace the allow-all default with grants like the ones in Setups for you. |
| 7. Tidy up | Machines page | Disable key expiry on servers, tag them, and remove old devices. |
Linux server#
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --auth-key=tskey-auth-XXXX --ssh --advertise-tags=tag:server
tailscale ip -4 # its 100.x address
tailscale status # every peer and how you reach it
macOS and Windows#
Install the app, click Log in, and use the menu bar or system tray icon. The CLI is available too: on a Mac it lives inside the app, and the app's settings offer to install it on your PATH.
Docker sidecar#
services:
tailscale:
image: tailscale/tailscale:latest
hostname: myapp
environment:
- TS_AUTHKEY=tskey-auth-XXXX
- TS_STATE_DIR=/var/lib/tailscale
- TS_EXTRA_ARGS=--advertise-tags=tag:server
volumes:
- ts-state:/var/lib/tailscale
app:
image: your/app
network_mode: service:tailscale
volumes:
ts-state:
network_mode: service:tailscale puts the app on the sidecar's network, so the app is reachable at myapp on your tailnet. Without the state volume, every restart registers a new device.
Platforms with no network device (Heroku, Cloud Run, some containers)#
tailscaled --tun=userspace-networking \
--socks5-server=localhost:1055 \
--outbound-http-proxy-listen=localhost:1055 &
tailscale up --auth-key=tskey-auth-XXXX --hostname=myapp
ALL_PROXY=socks5://localhost:1055/ curl http://home-pc:8080
Apps only reach the tailnet if they send their traffic through that proxy.
Removing it#
sudo tailscale logout signs the device out and expires its key; delete it on the Machines page to remove it from the list. sudo tailscale down only disconnects it until the next up.
Security model and limits#
What Tailscale protects, what it trusts, and where it stops.
| Question | Answer |
|---|---|
| Can Tailscale read my traffic? | No. Traffic is encrypted end to end with WireGuard between your devices. DERP relays forward packets they cannot decrypt. |
| What does Tailscale's server know? | Your devices, their public keys, names, IP addresses and endpoints, your policy file, and when devices connect. Flow logs, if you turn them on, record who talked to whom, never content. |
| Where are private keys? | Only on each device. They never leave it. |
| What if Tailscale's control server were compromised? | It could in principle hand your devices a rogue public key. Tailnet Lock is the defence: devices then refuse keys you did not sign. |
| What if my identity provider account is taken over? | The attacker can add devices as you. Use strong MFA at the provider, and consider device approval. |
| What if a device is stolen? | Remove it from the Machines page; it loses access at once. Key expiry limits how long a forgotten device stays trusted. |
| Is the code open? | The client daemon, CLI, DERP and the Linux and Android apps are open source (BSD-3). The macOS and Windows GUIs and the control server are closed. |
| Is it audited? | Tailscale publishes its security bulletins and holds SOC 2 Type II; see its security page. |
Firewall needs. Everything is outbound: TCP 443 to the control plane and DERP, UDP 41641 for direct WireGuard (any UDP port works), and UDP 3478 for STUN. No inbound ports are needed. The admin console moved to console.tailscale.com in July 2026, so allow-lists that name login.tailscale.com need both.
Limits worth knowing#
Speed. Direct connections run near line speed; userspace mode and DERP relays are slower. A relayed link is fine for SSH and dashboards and poor for large transfers.
One tailnet per device. A device belongs to one tailnet at a time. Fast user switching swaps between accounts, but not both at once.
Plan limits. Personal allows 6 users and is for non-commercial use; a business tailnet should be on Standard or above.
No layer 2. Tailscale routes IP packets. Broadcast and multicast discovery (some games, mDNS, Wake-on-LAN) do not cross it; ZeroTier does layer 2.
Overlapping subnets. Two subnet routers advertising the same 192.168.1.0/24 conflict. 4via6 routing exists for that case.
Funnel is not a CDN. It suits small sites and webhooks, not heavy public traffic; ports are limited to 443, 8443 and 10000.
Agents still need their own limits. Tailscale decides which machines an agent box can reach. It does not stop the agent doing harm on the box itself.
Troubleshooting#
Start every problem with these three commands; most answers are in their output.
tailscale status # is the peer online, and is the link direct or relayed?
tailscale ping <peer> # does it answer, and through which path?
tailscale netcheck # what does your network allow (UDP, NAT type, nearest DERP)?
| Symptom | Likely cause | Fix |
|---|---|---|
| Peer shows offline | Tailscale stopped there, or its key expired | On that device: sudo tailscale up. If expired: sudo tailscale up --force-reauth, then disable key expiry for servers |
| Can ping, but the app will not connect | Access policy blocks that port, or the app listens only on 127.0.0.1 | Check grants in Access controls (the policy's tests help); make the app listen on 0.0.0.0 or the 100.x address |
| Slow transfers | Link is relayed through DERP | tailscale ping shows "via DERP". Open outbound UDP, or add a peer relay on a box with a good network |
Name like home-pc does not resolve | MagicDNS off, or the OS is ignoring Tailscale's DNS | Turn on MagicDNS; use the full home-pc.<tailnet>.ts.net; on Linux check resolvectl status |
| SSH asks for a password or is refused | You are using normal SSH, not Tailscale SSH, or no SSH rule matches | Run tailscale up --ssh on the server and add an ssh rule to the policy |
| "Machine needs approval" | Device approval is on | Approve it on the Machines page |
| Subnet or exit node does nothing | Route not approved, or IP forwarding off | Approve the route on the Machines page; enable net.ipv4.ip_forward; on clients, select the exit node or accept routes with --accept-routes (Linux) |
| Docker container is a new device after every restart | No persistent state | Put TS_STATE_DIR on a volume |
| Corporate network blocks it | Only HTTPS allowed out | Tailscale falls back to DERP over TCP 443, so it should still work, just slower |
| Funnel URL does not load | Funnel not allowed in the policy, or HTTPS not enabled | Enable HTTPS in the DNS page; add the funnel node attribute; check tailscale funnel status |
| Another VPN is running | Two VPNs fighting over routes and DNS | Turn one off, or use split tunnelling in the other |
If you are still stuck, tailscale bugreport prints an ID you can give to Tailscale support, without sharing your logs publicly.
Cheat sheet#
| Task | Command |
|---|---|
| Join the tailnet (browser sign-in) | sudo tailscale up |
| Join with a key, as a tagged server with SSH | sudo tailscale up --auth-key=tskey-... --advertise-tags=tag:server --ssh |
| Disconnect / reconnect | sudo tailscale down / sudo tailscale up |
| Sign out | sudo tailscale logout |
| My addresses | tailscale ip |
| All peers and how I reach them | tailscale status |
| Test a path | tailscale ping home-pc |
| Check my network | tailscale netcheck |
| SSH in | tailscale ssh you@agent-box |
| Share a local port with my tailnet | tailscale serve --bg 3000 |
| Share a local port with the internet | tailscale funnel --bg 3000 |
| See what is served | tailscale serve status |
| Stop serving | tailscale serve reset |
| Send a file | tailscale file cp notes.pdf my-phone: |
| Receive files | sudo tailscale file get ~/Downloads |
| Offer this machine as an exit node | sudo tailscale set --advertise-exit-node |
| Use an exit node | sudo tailscale set --exit-node=home-pc |
| Stop using it | sudo tailscale set --exit-node= |
| Route a home LAN | sudo tailscale set --advertise-routes=192.168.1.0/24 |
| Accept routes (Linux client) | sudo tailscale set --accept-routes |
| Change a setting without re-joining | sudo tailscale set --<flag> |
| Renew an expired key | sudo tailscale up --force-reauth |
| Tailnet Lock status | tailscale lock status |
| Update the client | sudo tailscale update |
| Version | tailscale version |
tailscale set changes one setting and keeps the rest. tailscale up with flags resets any flag you leave out, which is the most common way people accidentally turn off SSH or routes.
FAQ#
Is Tailscale a VPN? Yes, but not the kind that hides your location by default. It connects your own devices privately. It only acts like a privacy VPN when you route traffic through an exit node or the Mullvad add-on.
Is the free plan enough for me? For personal, non-commercial use, yes: 6 users, plenty of devices, and nearly every feature in this tab. Paid plans add business use, more users, and controls such as flow logs.
Does it slow my internet down? No. Only traffic to your 100.x devices uses Tailscale unless you pick an exit node. Normal browsing goes out as usual.
Can Tailscale see my files or my traffic? No. Encryption keys stay on your devices. Tailscale sees which devices exist and when they connect, not what they send.
What if Tailscale goes down? Existing connections keep working, because traffic does not pass through its servers. New devices cannot join and policy changes wait until it is back.
Do I still need SSH keys? Not with Tailscale SSH: the tailnet identity is the authentication. Plain SSH over the tailnet still works if you prefer your keys.
Can I use it with Cloudflare Tunnel or another VPN? With Cloudflare Tunnel, yes; they solve different problems. With another full VPN, usually only one can manage routes and DNS at a time.
Does it work behind a strict school, hotel or office network? Usually. If UDP is blocked it falls back to relays over HTTPS port 443, which is slower but works.
Can friends reach one of my machines without joining my tailnet? Yes: share that one device with them by email or link. They see only that device.
Can I put a public website on it? For small sites and webhooks, Funnel works. For anything busy, use a proper host or Cloudflare.
Is it safe to give an AI agent access to my tailnet? Give it a tag and grant it nothing outbound, as in Setups for you. Then it can be reached but cannot reach the rest of your machines.
Can I avoid Tailscale's servers entirely? Yes, with Headscale, at the cost of running it yourself and losing Funnel and a few other features.
Sources#
Checked on November 15, 2026. Tailscale moves fast, so prices and plan limits are the first things to recheck.
How it works: How Tailscale works · How NAT traversal works · NAT traversal improvements · Control and data planes · Encryption · Key management · Node keys · Connection types · DERP servers · Peer relays GA · Throughput · Firewall ports
Addresses and DNS: IP and DNS addresses · MagicDNS · Tailnet name · HTTPS certificates
Access control: Grants syntax · Grants vs ACLs · Policy file · Auth keys · Key expiry · Tailnet Lock · Identity providers
Features: Exit nodes · Subnet routers · App connectors · Mullvad exit nodes · Services GA · Tailscale SSH · Funnel · Serve CLI · Taildrop · Sharing · Ephemeral nodes · Workload identity GA · GitHub Action · Docker parameters · Userspace networking · Logging · Aperture GA
Pricing and company: Pricing · Pricing v4 announcement · Changelog · Open source · Security
Self-hosting and alternatives: Headscale docs · Headscale on GitHub · ZeroTier pricing · NetBird pricing · Twingate pricing · OpenVPN pricing · Cloudflare Zero Trust plans
Where sources disagree#
Free trial. The pricing FAQ describes a 14-day trial of the top plan; the page's own summary says a 7-day Premium trial. Treat the length as uncertain until you start one.
Old device limits. Some third-party comparison sites still list the pre-April 2026 limits (100 devices and 20 tagged resources on the free plan). The pricing page is the authority.
Tagged resources. Third-party sites say every plan allows 50 tagged resources; Tailscale's own pricing table words this differently per plan.
Services GA date. The changelog lists January 27, 2026; the blog announces general availability on February 19, 2026.
Headscale version. Its docs show 0.29.7; GitHub's latest-release page showed 0.29.6 (October 24) when checked.
Plan names in older docs. The Tailnet Lock and SSH session recording pages still use plan names from before Pricing v4 ("Personal and Enterprise"), so their plan notes may be out of date.
ZeroTier's free tier. Older reviews say 25 devices; ZeroTier's current page says 10.
Headscale and Tailnet Lock. Headscale's feature list does not mention Tailnet Lock, so support is unconfirmed rather than ruled out.