Skip to content

MrCee/tailscale-headless-macos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

tailscale-headless-macos

Platform Arch Runtime Supervisor Mode DNS Goal License


🧠 What this is

A simple, reliable way to set up Tailscale on macOS without needing the GUI app.

This project:

  • installs and runs tailscaled via Homebrew
  • manages it with a system LaunchDaemon
  • configures MagicDNS explicitly

It’s designed for machines that you want online and reachable β€” without needing to log in or manage an app.

Set it up once β€” the machine stays connected, even before login.


🎯 When this makes sense

This is not for everyone.

Use it if you want:

  • a Mac that stays connected even when nobody is logged in
  • remote access to machines like iMacs, minis, or lab devices
  • predictable DNS behaviour (no mystery breakage)
  • to avoid the macOS Tailscale GUI entirely

If you’re happy using the official app β€” you probably don’t need this.


✨ Features

  • Fully headless tailscaled
  • Starts at boot via LaunchDaemon
  • Explicit MagicDNS resolver setup
  • Cleans up stale DNS configs automatically
  • Safe for zsh environments
  • Structured workflows:
    • install
    • verify
    • repair
    • uninstall
  • Smart hostname detection
  • Warning if hostname doesn’t match expectation
  • Fallback startup if LaunchDaemon fails

🧱 How it fits together

Homebrew
   ↓
tailscaled
   ↓
LaunchDaemon
   ↓
/etc/resolver/*
   ↓
macOS DNS
   ↓
MagicDNS

βš™οΈ Required configuration

TAILNET_DOMAIN

You must set your tailnet domain.

Example:

example-tailnet.ts.net

Find it with:

tailscale dns status --all

or via:

  • Tailscale Admin Console β†’ DNS

Do not guess this β€” it must be exact.


πŸ–₯️ Hostname behaviour

Controls:

tailscale up --hostname=...

If not set, it’s auto-detected from:

  1. LocalHostName
  2. ComputerName
  3. hostname -s

If you override it and it differs β€” you’ll get a warning.

Best practice:

  • keep it aligned with your Mac name
  • only override when you actually mean to

πŸ“‹ Requirements

  • Tailscale account
  • existing tailnet
  • tailnet domain
  • MagicDNS enabled (recommended)

πŸš€ Quick start

1. Clone

git clone https://github.com/MrCee/tailscale-headless-macos.git
cd tailscale-headless-macos

2. Create .env

cp .env.example .env

Edit:

TAILNET_DOMAIN=your-tailnet.ts.net

Optional:

TS_HOSTNAME=your-mac-name

3. Install

./install.sh

This will:

  • install or relink Tailscale
  • install LaunchDaemon
  • start tailscaled
  • configure DNS resolvers
  • optionally authenticate the node

4. Verify

./verify.sh

5. Repair DNS (if needed)

./fix-magicdns.sh

6. Uninstall

./uninstall.sh

πŸ” Script overview

install.sh

Main setup flow:

  • ensures sudo session
  • installs or relinks Tailscale
  • prepares state + logs
  • installs LaunchDaemon
  • starts daemon
  • writes resolver files
  • flushes DNS
  • optionally runs tailscale up

Includes fallback if LaunchDaemon bootstrap fails.


verify.sh

Read-only diagnostics:

  • binary check
  • daemon state
  • LaunchDaemon status
  • socket presence
  • resolver files
  • DNS resolution
  • logs

Helps identify partial vs healthy setups.


fix-magicdns.sh

DNS repair only:

  • ensures /etc/resolver exists
  • removes stale *.ts.net files
  • rewrites managed resolvers
  • flushes DNS

uninstall.sh

Clean removal:

  • stops daemon
  • removes LaunchDaemon
  • clears state + logs
  • removes resolver files
  • flushes DNS

Optional:

REMOVE_BREW_PACKAGE=true

🌐 MagicDNS model

Resolvers are explicitly managed:

/etc/resolver/ts.net
/etc/resolver/<tailnet>.ts.net
/etc/resolver/search.tailscale

This avoids common macOS DNS edge cases in headless setups.

Old resolver files are automatically cleaned:

/etc/resolver/*.ts.net

⚠️ Known behaviour

DNS may take a moment

Right after install or login:

tailscale status

You may briefly see stale data β€” give it a few seconds.


πŸ§ͺ Typical workflows

Fresh setup

cp .env.example .env
# edit .env
./install.sh
./verify.sh

Fix DNS issues

./fix-magicdns.sh
./verify.sh

Remove everything

./uninstall.sh

🧩 Design approach

  • keep everything explicit
  • run at system level, not user level
  • avoid hidden macOS behaviour
  • separate install / verify / repair clearly
  • make failures visible and fixable

πŸ–₯️ Tested on

  • macOS Intel
  • macOS Apple Silicon
  • Homebrew installs

πŸ‘€ Author

MrCee


πŸ’‘ Summary

Turn a Mac into a quiet, always-available Tailscale node.

No GUI. No surprises. Just works.

About

Run Tailscale headless on macOS using Homebrew and launchd, with pre-login networking and consistent MagicDNS resolution.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages