Access Any Device from Anywhere — How Tailscale Replaced My Entire VPN Setup
How Tailscale creates a private mesh network between your Mac, Windows, and Android devices — with zero port forwarding, no public IP, and SSH access that actually works.
Access Any Device from Anywhere — How Tailscale Replaced My Entire VPN Setup
Every developer who works across multiple devices has hit this wall. You need to grab a file from your desktop at home, or run a command on your Windows machine while sitting at a cafe with your Mac, or debug a service running on your laptop from your phone. The traditional answers are all terrible: expose ports to the internet and pray your firewall rules are correct, pay for a VPS to act as a relay, or set up a WireGuard config that breaks every time your ISP assigns a new IP.
Tailscale replaces all of that with something that feels absurdly simple for how powerful it is. Install it on your devices, log in with the same account, and they can see each other as if they were on the same local network. No port forwarding, no static IPs, no manual configuration. Your Mac gets an address like 100.75.2.78, your Windows machine gets 100.122.101.28, and you can SSH from one to the other as naturally as if they were sitting next to each other on the same desk.
What Tailscale Actually Is
Tailscale is a mesh VPN built on top of WireGuard. Instead of routing all your traffic through a central server, it creates direct encrypted connections between your devices. Each device runs a small agent that negotiates peer-to-peer tunnels with every other device in your network. The coordination happens through Tailscale's control plane, but the actual data flows directly between devices. Tailscale never sees your traffic.
The key insight is the 100.x.x.x address space. Tailscale assigns each device a stable IP in the CGNAT range that does not conflict with typical home or office networks. These addresses do not change. Your Mac is always 100.75.2.78 whether you are on home WiFi, a mobile hotspot, or a hotel network in another country. This stability is what makes it useful for SSH and service access — you hardcode the Tailscale IP once and it works forever.
The free tier covers up to 100 devices and 3 users. For personal use, that is effectively unlimited. No credit card required to start.
How It Works Under the Hood
When two Tailscale devices need to connect, they first try a direct connection over the local network. If both are behind NAT (which is almost always the case), Tailscale uses NAT traversal techniques borrowed from WebRTC: STUN to discover public addresses, hole punching to establish direct connections through NAT devices. If direct connection fails, Tailscale falls back to a relay server called DERP, which forwards encrypted packets between the two devices. The relay sees only encrypted WireGuard frames, so your data remains private even in the fallback path.
In practice, direct connection succeeds most of the time on home and office networks. The DERP relay adds some latency but keeps everything working. You can check which path a connection is using with tailscale ping <device-ip> — it will tell you whether the route is direct or going through DERP.
$ tailscale ping 100.122.101.28
pong from windows (100.122.101.28) via 192.168.1.5:41641 in 2ms
Two milliseconds means it went direct. If it says "via DERP" you are on the relay, which is still functional but ideally you would troubleshoot the NAT issue.
My Real Setup
I run Tailscale on three devices: a Mac as my primary development machine, a Windows desktop that I sometimes need for Windows-specific builds and testing, and an Android phone that I use for quick checks and captures on the go. Each device has a fixed Tailscale IP.
The Mac runs most of my services. I use Tailscale to SSH into it from my phone or from Windows. I run a local development server on port 3002 that I can access from any device on the Tailscale network by navigating to http://100.75.2.78:3002. No tunneling, no ngrok, no port forwarding on my router.
On Windows, I installed OpenSSH Server so I can run commands remotely from my Mac. I set up key-based authentication so there is no password prompt. From my Mac terminal I can do things like:
bashLoading...Loading syntax highlighting...
and get a directory listing from the Windows machine. This is useful for cross-platform development verification — checking that a build works the same way on both platforms, or grabbing a file from the Windows filesystem without leaving my Mac.
Setup Guide
macOS
Download Tailscale from the Mac App Store or install it via Homebrew:
bashLoading...Loading syntax highlighting...
Open the Tailscale app from your Applications folder. It will ask you to log in — you can use Google, GitHub, Apple, or a few other identity providers. Pick one and stick with it; all your devices need to be on the same account.
After login, the app shows your Tailscale IP address. Note this down. You can also find it anytime by running:
bashLoading...Loading syntax highlighting...
To enable SSH access to your Mac, turn on Remote Login in System Settings. Go to General, then Sharing, and toggle Remote Login to on. This starts the built-in SSH server on port 22.
For key-based authentication so you can connect without a password:
bashLoading...Loading syntax highlighting...
Copy the public key (id_ed25519.pub) to any other device you want to connect from. On Android, you can use Termux. On Windows, you can use ssh-copy-id from Git Bash or manually paste the key into the authorized_keys file.
Windows
Download Tailscale from the Microsoft Store or from tailscale.com/download. Install it, open it, and log in with the same account you used on your Mac.
Your Windows machine will get its own Tailscale IP. Note it down. You can find it by right-clicking the Tailscale tray icon and looking at the device details, or by running in PowerShell:
powershellLoading...Loading syntax highlighting...
For SSH access to the Windows machine, you need to install OpenSSH Server. Open PowerShell as Administrator and run:
powershellLoading...Loading syntax highlighting...
Verify it is running:
powershellLoading...Loading syntax highlighting...
You should see Status = Running.
If Windows Firewall blocks the connection, add a rule to allow inbound traffic on port 22:
powershellLoading...Loading syntax highlighting...
Next, copy your SSH public key from your Mac to the Windows machine. The easiest way is ssh-copy-id from your Mac:
bashLoading...Loading syntax highlighting...
If that does not work, you can do it manually. On Windows, create the .ssh directory and the authorized_keys file:
powershellLoading...Loading syntax highlighting...
Windows OpenSSH has strict permission requirements on authorized_keys. The file must be owned by the user and have limited access. Fix the permissions with:
powershellLoading...Loading syntax highlighting...
If your user is in the Administrators group, Windows also checks a second location for authorized keys. Copy the same key there too:
powershellLoading...Loading syntax highlighting...
Restart the SSH service and test from your Mac:
powershellLoading...Loading syntax highlighting...
bashLoading...Loading syntax highlighting...
One more thing. Windows defaults to cmd.exe as the SSH shell, which means PowerShell syntax does not work in remote commands. If you prefer PowerShell, set it as the default SSH shell:
powershellLoading...Loading syntax highlighting...
With PowerShell as the default shell, remember that && is bash syntax. Use ; instead for chaining commands. Or force a specific mode per command:
bashLoading...Loading syntax highlighting...
Common Windows SSH pitfalls:
If you have .bashrc, .bash_profile, or .zshrc in your Windows home directory (left over from Git Bash or WSL), PowerShell will try to parse them on SSH login and throw errors. Rename them:
powershellLoading...Loading syntax highlighting...
If you use oh-my-posh or PSReadLine in your PowerShell profile, these also break over SSH because they require a virtual terminal that SSH does not provide. Create a minimal SSH-safe profile:
powershellLoading...Loading syntax highlighting...
Android
Install Tailscale from the Google Play Store. Open it, log in with the same account, and grant the VPN permission when prompted. Your phone will get a Tailscale IP in the same 100.x.x.x range.
The Android Tailscale app also provides a quick access tile in your notification shade. You can toggle the VPN on and off without opening the app.
From your phone, you can now access any service running on your Mac or Windows machine. Open a browser and navigate to http://100.75.2.78:3002 to hit a local dev server on your Mac. Use an SSH client app like Termux or JuiceSSH to get a terminal on your Mac:
bashLoading...Loading syntax highlighting...
This is surprisingly useful. I use it to check on running services, restart a crashed process, or pull a file I need while away from my desk. The connection is encrypted end to end and works on mobile data, not just WiFi.
Connecting It All Together
The pairing process is straightforward. Install Tailscale on every device, log in with the same account, and they are all on the same network automatically. You do not need to manually pair devices or exchange keys — Tailscale handles device discovery through its control plane.
If you want to restrict which devices can talk to each other, Tailscale supports ACLs (access control lists) that let you define rules like "only the Mac can SSH into the Windows machine" or "the phone can only reach port 3002 on the Mac." For personal use with a small number of devices, the default permissive policy is fine.
Verify everything is working:
bashLoading...Loading syntax highlighting...
When Cloudflare Tunnel Makes Sense Too
Tailscale is perfect when all your devices are on the same account. But what if you want to share a service with someone who is not on your Tailscale network, or expose something publicly for a webhook callback? That is where Cloudflare Tunnel comes in.
bashLoading...Loading syntax highlighting...
This gives you a temporary public URL like https://xxx.trycloudflare.com that anyone on the internet can reach. The traffic still flows through an encrypted tunnel, but instead of being limited to your Tailscale network, it is publicly accessible. The URL changes each time you restart the tunnel, which is fine for quick demos or webhook testing. For permanent public URLs you would need a Cloudflare account and a custom domain.
I use Tailscale for all my personal device-to-device access and Cloudflare Tunnel for the rare case where I need to expose something to the public internet temporarily. The two tools complement each other without conflict.
Why Not WireGuard Directly
You could set up raw WireGuard without Tailscale and achieve a similar result. The problem is the maintenance burden. With WireGuard you need to manually generate keys for each device, configure peer endpoints, handle NAT traversal yourself, and update configs whenever an IP changes. If your home ISP changes your public IP, your WireGuard tunnels break until you update the configs on every device.
Tailscale automates all of that. Key rotation, NAT traversal, device discovery, ACLs — it handles the operational complexity that makes raw WireGuard impractical for most people. You are still using WireGuard under the hood, but the experience is closer to "log in and it works" than "spend a weekend configuring iptables."
Final Thought
Tailscale solved a problem I had been duct-taping together for years. I no longer think about how to reach my devices. My Mac, my Windows machine, and my phone are all on the same private network no matter where they are physically. I can SSH between them, access local services, and transfer files without exposing anything to the public internet or paying for a relay server. The free tier covers everything I need, and the setup took less than 20 minutes across all three platforms. That is the kind of tool that stays in your stack permanently.
Related Posts
Stop Paying for Notes — Obsidian + Syncthing Is All You Need
A free, private, cross-platform note-taking system using Obsidian and Syncthing — with setup guides for macOS, Windows, and Android. No subscriptions, no cloud, no compromises.
Read moreSetting Up Hermes Agent — My AI-Powered Dev Assistant
How I set up Hermes Agent with 40+ custom skills, RTK token optimization, and automated workflows for finance, development, and productivity.
Read more