Making a Mac Mini headless: FileVault, auto-login, and launchd
It runs headless, and is accessed purely over Tailscale SSH. When macOS applied a software update and rebooted the machine, I lost all access — the disk was locked behind FileVault, requiring physical presence to enter a password before the system was usable over the network.
This machine runs the Karkhana forge — a personal workshop for AI agents and software projects.
The problem
The Mac Mini runs headless in a closet. After a restart triggered by either a power outage or an automatic software update:
- FileVault showed the disk encryption unlock screen — boot was blocked until a password was entered at the physical console.
- Without a logged-in user session, SSH was unreachable.
- Tailscale connected at the network level but the SSH subsystem didn’t initialize until a user session existed.
- Even when Tailscale did initialize, it logged
all links down; pausingfor ~4 seconds during boot — the Ethernet interface took time to come up, buttailscaledstarted before the network was ready and couldn’t reach the control plane.
The root cause was FileVault. With it enabled, the machine stops at the unlock screen regardless of how it’s configured for network access.
Why headless matters here
This Mac Mini isn’t a desktop machine — it’s a workshop appliance. It runs my AI agent (Hermes) and hosts my software projects (the Karkhana forge). The goal is for it to be reachable over Tailscale SSH within seconds of any reboot, without me needing to be physically near it. That’s only possible if the machine boots to a usable state on its own.
What I changed
1. Disabled FileVault
sudo fdesetup disable
This requires the user password. After this, the Mac boots directly to the login screen, bypassing the FileVault unlock prompt entirely.
Tradeoff: The disk is no longer encrypted at rest. Appropriate for this machine — it’s in a physical location I control, and the data is protected by my three-tier backup strategy rather than full-disk encryption.
2. Enabled auto-login
The Mac Mini runs an agent named Tara. The local user account on the machine is also named tara — matching the agent name. With auto-login enabled, the system logs in as tara automatically after boot:
sudo defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser -string tara
This starts the user session immediately, which allows SSH user authentication and Tailscale SSH to work without any physical interaction.
3. Added WaitForNetwork to Tailscale launchd plist
The Tailscale LaunchDaemon plist at /Library/LaunchDaemons/homebrew.mxcl.tailscale.plist was starting tailscaled before the network interface was available. I added the WaitForNetwork key so launchd holds the service until the network is confirmed up:
<key>WaitForNetwork</key>
<true/>
The full plist runs tailscaled as a LaunchDaemon with RunAtLoad and KeepAlive. After editing:
sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.tailscale.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.tailscale.plist
4. Verified SSH was enabled
sudo systemsetup -getremotelogin
# Remote Login: On
SSH was already on. It simply wasn’t reachable before because there was no user session to authenticate against.
On LaunchAgents vs LaunchDaemons
I had previously moved the Hermes services from LaunchAgents to LaunchDaemons specifically so they would boot without requiring a user to be logged in. The intent was correct — LaunchDaemons run at the system level, before any user logs in. However, two obstacles prevented this from working in practice:
- FileVault — even if the daemons started, the network and SSH were blocked at the unlock screen
- Tailscale network timing — the daemon started before the network stack was ready, causing connection failures
With FileVault disabled and auto-login configured, the LaunchDaemon approach now works as intended. The distinction between LaunchDaemons and LaunchAgents becomes less critical — with auto-login, a user session exists within seconds of boot anyway. The Hermes daemons (ai.hermes.dashboard, ai.hermes.gateway) remain correctly configured as system-level LaunchDaemons with UserName set to tara, and they start after the user session exists.
Verification
After a full reboot, I verified the following from a remote machine:
tailscale status
# ← Tailscale connected, machine reachable over tailnet
ssh tara@<machine-name>.<tailnet>.ts.net
# Login successful, user session available
Hermes gateway and dashboard were also reachable over Tailscale SSH within ~15 seconds of reboot completing.
What I’d do differently
If I needed to keep FileVault enabled, the next option would be to store the FileVault key with a Jamf-compatible MDM so the Mac can unlock itself on boot. That’s more infrastructure than one machine warrants.
The simpler path — and the one I took — is accept the trade: no encryption at rest, full remote access from boot.