Use the Tailscale brew formula, not the cask
Quick note to past me: when installing Tailscale on a headless Mac,
brew install tailscale (the formula). Not brew install --cask tailscale-app.
What was happening
I wanted Tailscale on a Mac mini that I drive entirely over SSH. Default
muscle memory said brew install --cask for anything with a GUI. So I did
that, and the install succeeded, and tailscale up over SSH did nothing
useful. The cask installs the Network Extension variant — a sandboxed
macOS app that requires you to click "allow" in a menu-bar UI to grant
the Network Extension permission. With no display attached and no GUI
session running, there is no menu bar to click.
What I found
The brew cask is the App Store-style Network Extension build. It exists because that's the only shape Apple really wants new "VPN-like" software to take on macOS. It is the wrong choice for a headless box.
The brew formula is the open-source Linux-style daemon: a tailscaled
binary that runs as a LaunchDaemon, and a tailscale CLI. It works
identically to the Linux setup and doesn't need GUI interaction.
The fix
Uninstall the cask, install the formula, start the daemon:
brew uninstall --cask tailscale-app
brew install tailscale
sudo brew services start tailscale
The formula drops a LaunchDaemon plist at
/Library/LaunchDaemons/homebrew.mxcl.tailscale.plist and the CLI lands
at /opt/homebrew/bin/tailscale on Apple Silicon. From there:
sudo tailscale up
prints an auth URL. Click it from any browser on any device, sign in, the Mac is in the tailnet. Done.
What I'd do differently
When brew install --cask shows up in my head for headless infrastructure,
I should stop and check brew info <name> first. If the cask description
mentions "Network Extension," "menu bar," or "App Store," it's the wrong
tool for SSH-only use. Default to the formula and only reach for the cask
if the formula doesn't exist.