user@homelab:~/docs$ cat remote-access.md
Remote access (Tailscale, k9s)
SSH to the server from anywhere without open ports, and a cluster overview in k9s
# contents
How it works
Tailscale creates a private network (tailnet) between your own devices only: the server, the Mac and the iPad. Each device gets a 100.x.y.z address and a name in the <tailnet>.ts.net domain. Connections are encrypted (WireGuard) and established outbound, so nothing is opened on the router.
Mac / iPad (anywhere) ──WireGuard──▶ homelab.<tailnet>.ts.net
(no open ports, direct connection even through NAT)| Tailscale | Cloudflare Access / WARP | |
|---|---|---|
| SSH from the Mac and from Termius on the iPad | ✅ unchanged | ⚠️ ProxyCommand or WARP |
| any port (SSH, later Grafana) | ✅ | ⚠️ more setup |
| server visible from the internet | ❌ not at all | a login page |
| dependency | independent of Cloudflare | same vendor as the site |
Hence: public site via Cloudflare, administration via Tailscale.
Server
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale uptailscale up prints a login link; opening it in a browser adds the server to the tailnet. The install script adds the official apt repository, so Tailscale is updated with the system.
tailscale ip -4
tailscale status- SSH stays OpenSSH with keys and passwords disabled. Tailscale’s own login (
tailscale up --ssh) is not used; Tailscale is only the encrypted path. - Key expiry is disabled for the server in the admin console (Machines → homelab → Disable key expiry), otherwise it would drop off after 180 days. It stays enabled for clients.
Mac and iPad
- The Tailscale app (Mac App Store / App Store), signed in with the same account.
- macOS asks to add a VPN configuration and a network extension; both are required. Only tailnet traffic goes through Tailscale, everything else is unchanged (no exit node).
- MagicDNS names the devices; the server is
homelab.<tailnet>.ts.net.
SSH config on the Mac:
Host homelab
HostName homelab.<tailnet>.ts.net
User <user>
IdentityFile ~/.ssh/id_ed25519
AddKeysToAgent yes
UseKeychain yesOne config works at home and away. At home Tailscale detects the shared network and connects directly over Wi-Fi.
Termius on the iPad: a host with hostname homelab.<tailnet>.ts.net, the same user and key. Optionally a second host with the home IP address for when Tailscale is not running on the iPad.
Verification
tailscale ping homelab
ssh homelabtailscale ping output | Meaning |
|---|---|
via <lan-ip>:41641 | at home, directly over Wi-Fi |
via <public-ip>:<port> | away, direct connection through NAT |
via DERP(<region>) | through a Tailscale relay; works, just slower |
Test from outside: the Mac on a phone hotspot, the iPad on mobile data.
kubectl on the server only
The cluster is managed on the server over SSH (ssh homelab → k …). kubectl on the Mac is deliberately not set up:
- the cluster admin certificate stays on the server only,
- no risk of mixing it up with other clusters in the Mac’s kubeconfig,
- the CKAD exam is taken in a terminal on a remote machine anyway.
k9s
k9s is a terminal “GUI” for Kubernetes: pods, logs, events and resources at a glance. It works over SSH from the Mac and the iPad.
Installed from the official release with checksum verification:
K9S_VER=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/derailed/k9s/releases/latest | sed 's#.*/tag/##')
cd /tmp
curl -fsSLO "https://github.com/derailed/k9s/releases/download/${K9S_VER}/k9s_linux_amd64.deb"
curl -fsSLO "https://github.com/derailed/k9s/releases/download/${K9S_VER}/checksums.sha256"
grep ' k9s_linux_amd64.deb$' checksums.sha256 | sha256sum -c -
sudo apt install -y ./k9s_linux_amd64.deb
rm -f k9s_linux_amd64.deb checksums.sha256sha256sum -cmust printOK, otherwise the package is not installed,- k9s uses the same kubeconfig as
kubectl(~/.kube/config), - a
.debfrom GitHub is not updated byapt upgrade; for a new version, repeat the steps.
Handy k9s commands: :pods, :deploy, :events, :kustomizations (Flux), l logs, d describe, 0 all namespaces.