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.

text
Mac / iPad (anywhere) ──WireGuard──▶ homelab.<tailnet>.ts.net
                      (no open ports, direct connection even through NAT)
TailscaleCloudflare 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 alla login page
dependencyindependent of Cloudflaresame vendor as the site

Hence: public site via Cloudflare, administration via Tailscale.

Server

shell @ server
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

tailscale 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.

shell @ server
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

  1. The Tailscale app (Mac App Store / App Store), signed in with the same account.
  2. 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).
  3. MagicDNS names the devices; the server is homelab.<tailnet>.ts.net.

SSH config on the Mac:

ssh config @ mac
Host homelab
    HostName homelab.<tailnet>.ts.net
    User <user>
    IdentityFile ~/.ssh/id_ed25519
    AddKeysToAgent yes
    UseKeychain yes

One 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

shell @ mac
tailscale ping homelab
ssh homelab
tailscale ping outputMeaning
via <lan-ip>:41641at 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:

shell @ server
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.sha256
  • sha256sum -c must print OK, otherwise the package is not installed,
  • k9s uses the same kubeconfig as kubectl (~/.kube/config),
  • a .deb from GitHub is not updated by apt upgrade; for a new version, repeat the steps.

Handy k9s commands: :pods, :deploy, :events, :kustomizations (Flux), l logs, d describe, 0 all namespaces.