Tailscale - home LAN from anywhere
Tailscale is the easiest way I know of to reach a machine remotely on your home LAN from the internet, without port-forwarding, without a public IP, and without poking holes in your router. WireGuard-based; client is fully open-source; installable via snap.
How it works
Tailscale builds a mesh VPN on top of WireGuard.
Every machine you install Tailscale on gets its own private IP in the
100.64.0.0/10 range and can talk directly to every other machine in your
“tailnet” over an encrypted WireGuard tunnel.
The clever bit is the coordination server (Tailscale’s SaaS control plane):
- You log in on each machine via SSO (Google, GitHub, Microsoft, …). No passwords, no keys to copy around.
- The coordination server exchanges WireGuard public keys between your machines and tells them each other’s current public IP+port.
- Machines then attempt direct peer-to-peer connections using NAT traversal (UDP hole-punching, STUN-style). This works even when both peers are behind NAT - no port forwarding needed.
- If NAT traversal fails (symmetric NAT, CGNAT, strict firewalls), traffic falls back to Tailscale’s DERP relays - encrypted, but slower. Tailscale can’t read the traffic either way: the WireGuard keys never leave your devices.
Tailscale itself is not fully open source - the coordination server is proprietary, but the clients are. The free plan covers up to 100 devices and 3 users, which is plenty for personal use. If you want a fully OSS setup, Headscale is a drop-in replacement for the coordinator, but honestly - for home use the free plan is just fine.
Connecting two Ubuntu machines
On both machines (say, your home server and your laptop):
sudo snap install tailscale
sudo tailscale up
The tailscale up command prints a URL - open it in a browser and log in with
your SSO account of choice. Both machines must log in to the same tailnet
(same account).
That’s it. Check assigned IPs:
tailscale ip -4 # your machine's tailnet IP
tailscale status # all peers in your tailnet
From now on, you can ssh user@100.x.y.z from your laptop to your home
server from anywhere on the internet, as if they were on the same LAN.
Useful extras
- MagicDNS: enable it in the admin console, then you can
ssh user@homeserverusing the machine’s hostname instead of its tailnet IP. - Subnet router: if you want to reach other devices on your home LAN
(printer, NAS, router admin) without installing Tailscale on each one,
run
sudo tailscale up --advertise-routes=192.168.1.0/24on your home server and approve the route in the admin console. Your laptop can then reach192.168.1.xdirectly through the server. - Exit node:
sudo tailscale up --advertise-exit-nodeturns a machine into a VPN gateway - route all your laptop’s traffic through your home connection when on untrusted Wi-Fi. - Tailscale SSH:
sudo tailscale up --sshreplaces sshd key management with tailnet identity. Nice, but optional.
Stay secure
Tailscale doesn’t expose your services to the public internet, but every service
listening on 0.0.0.0 is now reachable from every other machine in your tailnet.
If your laptop ever gets compromised, the attacker inherits that access. So:
audit what’s actually listening before you trust the tunnel.
sudo netstat -tnlp # TCP listeners + the process behind each
sudo netstat -unlp # same for UDP
sudo ss -tnlp # ss is the modern replacement, same flags
For each line, ask: do I need this? Does it have to listen on 0.0.0.0, or
would 127.0.0.1 be enough? If you don’t recognise the process, uninstall the
package. Typical offenders on a fresh Ubuntu install are CUPS (printing), Avahi
(mDNS), and whatever lingering dev server you forgot about. Bind database
servers (PostgreSQL, Redis, MySQL) to 127.0.0.1 unless you genuinely need
remote access - they were never meant to face a network without auth hardening.
SSH: keys only, no passwords
Over Tailscale you’ll mostly live inside SSH, so harden it. Password auth is the weakest link - brute-forceable, phishable, and replayable. Use a public key instead.
On your laptop, generate a key if you don’t have one:
ssh-keygen -t ed25519 -C "laptop"
Copy it to the server:
ssh-copy-id user@homeserver
Test that key auth works (ssh user@homeserver should not prompt for a
password), then on the server edit /etc/ssh/sshd_config (or drop a file
in /etc/ssh/sshd_config.d/ - it must end in .conf, e.g.
50-pubkey.conf):
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
Reload sshd:
sudo systemctl reload ssh
Keep a second terminal logged in while you do this - if you lock yourself out, you still have a way back in. From now on only someone holding your private key can log in, and a stolen or guessed password is worthless.
No port forwarding, no dynamic DNS, no fail2ban tuning. It just works.