# Remote Access to My Home Mac mini with Tailscale (No Static IP)

*My setup notes — what I did, why, and how to recover when things break.*

## The goal

I have a Mac mini sitting at home on a residential connection with **no static IP**. I want to:

*   SSH into it from my laptop **from anywhere**, using plain old OpenSSH (no `cloudflared`, no Tailscale SSH magic).
    
*   Reach the **rest of my home LAN** through it — printers, NAS, router admin page, other devices.
    
*   Keep it **secure enough to move sensitive data** with no realistic man-in-the-middle exposure.
    

I went with **Tailscale** instead of a Cloudflare tunnel. It's a WireGuard-based mesh: every device gets a stable `100.x.y.z` address that doesn't change even when my home IP does, NAT traversal handles the no-static-IP problem, and there's no port forwarding to set up.

## Why this is secure (the short version)

*   Each device generates its **own WireGuard keypair locally**. The private key never leaves the device, so Tailscale (the company) literally cannot decrypt my traffic.
    
*   Traffic is **end-to-end encrypted, point-to-point**. Even when it falls back through Tailscale's relay (DERP) servers, those only ever see already-encrypted packets.
    
*   The one residual trust is that Tailscale's coordination server hands out **honest public keys**. That's the only theoretical MITM seam — and **Tailnet Lock** (Part 2 below) closes it entirely.
    

> Reality check: device security and tight access rules matter more than the crypto. A compromised laptop or an over-broad ACL is a bigger real-world risk than WireGuard being broken.

* * *

## Part 1 — Core setup (no Tailnet Lock)

This is the part to actually do first. Get SSH + LAN access working and stable before adding any hardening.

### 1\. Install the right Tailscale build on the Mac mini

On macOS there are two builds. For an always-on machine that will act as a **subnet router**, install the **standalone build** (the `tailscaled` daemon + full CLI), *not* the App Store GUI version.

*   Standalone runs as a real system daemon, survives logout, and starts at boot.
    
*   It gives me the full `tailscale` CLI I need for `--advertise-routes`.
    

Download the standalone `.pkg` from [https://tailscale.com/download/macos](https://tailscale.com/download/macos).

For the **laptop**, either build is fine — the App Store version is easiest since it's just a client.

### 2\. Sign in on both devices

Same account on both so they land in the same tailnet.

On the Mac mini:

```bash
sudo tailscale up
```

It prints a login URL — open it, authenticate, approve the device. Do the same on the laptop (menu-bar icon → log in).

Verify they see each other:

```bash
tailscale status
```

### 3\. Enable MagicDNS (optional, recommended)

Admin console (`login.tailscale.com`) → **DNS** → enable **MagicDNS**. Lets me `ssh user@mac-mini` instead of memorizing the `100.x` address.

### 4\. Enable plain SSH on the Mac mini

This is the "just make it reachable, I'll use normal ssh" path — no Tailscale SSH.

*   **System Settings → General → Sharing → Remote Login = ON** (optionally restrict to my user).
    

That starts Apple's standard `sshd`. Tailscale isn't doing anything special — it's just the encrypted network path.

From the laptop, anywhere in the world:

```bash
ssh youruser@mac-mini        # with MagicDNS
# or
ssh youruser@100.x.y.z       # raw tailnet IP
```

Harden it with key-based auth:

```bash
ssh-copy-id youruser@mac-mini
```

Then optionally set `PasswordAuthentication no` in `/etc/ssh/sshd_config` for key-only access.

### 5\. Find my home subnet

On the Mac mini:

```bash
ipconfig getifaddr en0          # the mini's LAN IP, e.g. 192.168.1.42
netstat -rn | grep default      # confirms the gateway/router
```

If the mini is `192.168.1.42` with a typical `/24`, my subnet is `192.168.1.0/24`. **Adjust for your own network** — some routers use `192.168.0.0/24`, `10.0.0.0/24`, etc.

### 6\. Enable IP forwarding on the Mac mini

The mini has to forward packets bound for other LAN devices:

```bash
sudo sysctl -w net.inet.ip.forwarding=1
sudo sysctl -w net.inet6.ip6.forwarding=1
```

macOS does **not** persist sysctl across reboots, so make it permanent with a LaunchDaemon.

Create `/Library/LaunchDaemons/com.user.ipforwarding.plist`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.user.ipforwarding</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/sbin/sysctl</string>
    <string>-w</string>
    <string>net.inet.ip.forwarding=1</string>
    <string>net.inet6.ip6.forwarding=1</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>
```

Then load it:

```bash
sudo chown root:wheel /Library/LaunchDaemons/com.user.ipforwarding.plist
sudo launchctl load /Library/LaunchDaemons/com.user.ipforwarding.plist
```

Forwarding now re-enables automatically after every reboot.

### 7\. Advertise the subnet route

On the Mac mini (already up, so use `set`):

```bash
sudo tailscale set --advertise-routes=192.168.1.0/24
```

*(Or* `sudo tailscale up --advertise-routes=192.168.1.0/24` *to do it at login time. Both work.)*

### 8\. Approve the route in the admin console

Subnet routes are **double opt-in** — advertising isn't enough, I must approve.

Admin console → **Machines** → click the Mac mini → **Edit route settings** → toggle on `192.168.1.0/24` → **Save**.

### 9\. Use it from the laptop

macOS clients **use advertised subnets by default**, so the laptop picks up the route automatically once approved — no `--accept-routes` flag needed.

Now from anywhere:

*   Mac mini directly: `ssh youruser@mac-mini`
    
*   Printer / NAS / router admin / other LAN boxes: just use their normal `192.168.1.x` addresses, as if I were home.
    

### 10\. Keep the mini awake and online

**System Settings → Energy / Battery** → prevent sleep (or enable "wake for network access"). A sleeping mini drops off the tailnet and takes the LAN route with it.

### Verification checklist

*   \[ \] `tailscale status` on both → each sees the other.
    
*   \[ \] Mini shows it's advertising the route; admin console shows it **approved** (green).
    
*   \[ \] From a *genuinely remote* network (phone hotspot is easiest): `ssh mac-mini` works **and** I can reach a `192.168.1.x` LAN device.
    

> **Subnet collision gotcha:** if the remote network I'm on also uses `192.168.1.0/24`, routing gets ambiguous and LAN access misbehaves. Fix by changing my home router to a less common range like `192.168.50.0/24` or something in `10.x`.

* * *

## Part 2 — Enable Tailnet Lock later (optional hardening)

Do this **only after Part 1 is stable**. It removes the need to trust Tailscale's key distribution — even a malicious/compromised Tailscale couldn't silently insert a rogue node to MITM me.

### 1\. Update both clients

Any current Tailscale build is fine (Tailnet Lock has been GA since 2023).

### 2\. Decide signing nodes

I want redundancy so one failure doesn't strand me. With only a Mac mini + laptop, use **both** as signing nodes. *(Note: an Android phone can't be a signing node, if I add one later.)*

### 3\. Initialize from the admin console

Admin console → **Settings → Tailnet Lock** → follow the wizard. Select signing nodes; it hands me a `tailscale lock init ...` command to paste on a trusted node.

### 4\. Run init and **SAVE THE SECRETS**

Paste the command on the Mac mini. It prints **disablement secrets**. This is the critical part:

*   Disablement secrets are shown **only once**, at init. Lose them (and don't give one to Tailscale support) and **the tailnet can't be recovered**.
    
*   I only need **one** secret to disable the lock, though several are generated.
    
*   Store them in my password manager.
    
*   During setup, **opt to generate the extra disablement secret that's handed to Tailscale support** — that's my safety net against lock-out.
    

### 5\. Sign existing nodes

After init, existing devices must be signed by a trusted key. The console flags any "locked out" nodes; sign them from a signing node. From then on, **every new device must be signed** from the mini or laptop before it can connect — that's the tradeoff for not trusting Tailscale's key distribution.

### Undo it if needed

```bash
tailscale lock disable <one-of-your-disablement-secrets>
```

If a signing key is ever *compromised* (different from lost):

```bash
tailscale lock recover-compromised-key   # revokes the bad key, removes devices it signed
```

* * *

## Power-cut hardening (so a blackout isn't a lockout)

After a power outage, most of this heals itself **if** Part 1 was done as above:

*   `tailscaled` (standalone build) starts at boot and reconnects automatically.
    
*   A changed public IP doesn't matter — NAT traversal re-negotiates.
    
*   IP forwarding returns (LaunchDaemon `RunAtLoad`).
    
*   Subnet route + console approval persist; LAN access comes back.
    
*   SSH / Remote Login is a system service; it restarts at boot.
    

But two things will **strand me** if not handled:

### 1\. Make the mini power itself back on

By default a Mac can stay *off* after power returns. Turn on auto-restart:

```bash
sudo pmset -a autorestart 1
pmset -g | grep autorestart   # verify
```

*(Equivalent: System Settings → Energy → "Start up automatically after a power failure.")*

### 2\. FileVault decision — the big one

If FileVault is on, a cold boot **stops at the pre-boot unlock screen** and macOS never finishes booting until someone physically types the password. Until then: no Tailscale, no SSH, no LAN route — fully locked out remotely.

Tradeoff:

| FileVault | Pro | Con |
| --- | --- | --- |
| **Off** | Unattended recovery "just works" after a power cut | Disk not encrypted at rest (physical theft exposes data) |
| **On** | Stronger at-rest security | A cold boot likely needs physical access / KVM before remote access returns |

For an always-on server I want to reach remotely, I'm leaning **FileVault off** on this machine, relying on home physical security + key-only SSH + tight Tailscale ACLs instead. *(Reconsider if the mini holds genuinely sensitive data at rest.)*

### Nice-to-have

Set a **DHCP reservation** for the mini on the router so it always gets the same LAN IP. Not strictly required for subnet routing, but it avoids confusion and survives a router reset cleanly.

* * *

## Recover from… (scenario playbook)

Quick reference for when something breaks.

### Power outage, then power restored

*   **Expected:** mini auto-boots (if `pmset autorestart 1`), `tailscaled` reconnects, route + SSH come back on their own within a few minutes.
    
*   **If it doesn't come back:** check FileVault — a cold boot may be stuck at the unlock screen. Plug in a monitor/keyboard at home and log in. Confirm `pmset -g | grep autorestart` shows `1`.
    
*   **Prevent next time:** ensure auto-restart is on; decide consciously on FileVault.
    

### Mac mini reachable but I can't reach the LAN (printer/NAS)

1.  On the mini: `tailscale status` → is it still advertising the route?
    
2.  Admin console → Machines → mini → is the route still **approved** (green)?
    
3.  On the mini: `sysctl net.inet.ip.forwarding` → should be `1`. If `0`, the LaunchDaemon didn't load: `sudo launchctl load /Library/LaunchDaemons/com.user.ipforwarding.plist`.
    
4.  Am I on a remote network with the **same subnet** as home? That collision breaks LAN routing — switch networks or change my home subnet.
    

### Can't SSH in at all

1.  From the laptop: `tailscale status` → does it list the mini, and is the mini **online**?
    
2.  If the mini is offline → it's a power/network/FileVault issue at home (see power section).
    
3.  If online but SSH refused → Remote Login may have been turned off. Need physical/console access to re-enable **System Settings → Sharing → Remote Login**.
    
4.  Key-only auth and lost my key? Re-enable password auth locally, or add a new public key from the console.
    

### My home public IP changed (ISP reassigned it)

*   **Nothing to do.** This is exactly what Tailscale handles — NAT traversal re-establishes automatically. No reconfig.
    

### Router was reset / replaced

*   Re-check the **subnet CIDR** (Step 5) — it may have changed (e.g. back to `192.168.0.0/24`).
    
*   If it changed, re-advertise: `sudo tailscale set --advertise-routes=<new-subnet>` and re-approve in the console.
    
*   Re-add the **DHCP reservation** for the mini.
    

### Tailnet Lock locked me out (lost signing keys)

*   **Existing devices keep working** — only *adding new nodes* breaks.
    
*   If I still have a **disablement secret:** `tailscale lock disable <secret>`.
    
*   If I gave a secret to **Tailscale support:** contact them to disable.
    
*   **Worst case (no secrets anywhere):** abandon the tailnet, create a fresh one, reinstall Tailscale on both machines, re-auth, re-advertise the route. ~15 minutes at this scale. *(I always retain physical control of my own hardware — I'm never bricked out of the machine itself, only the old tailnet.)*
    

### Signing key compromised (Tailnet Lock)

```bash
tailscale lock recover-compromised-key
```

Revokes the bad key and automatically removes every device it signed. Then re-sign the legit devices.

### Mac mini sleeps and disappears from the tailnet

*   System Settings → Energy → disable sleep / enable "wake for network access."
    
*   Confirm it's on power (not relying on display sleep settings only).
    

### Tailscale client itself is acting up

```bash
sudo tailscale down && sudo tailscale up      # reconnect
tailscale netcheck                            # diagnose NAT / DERP / connectivity
```

As a last resort on the mini, uninstall and reinstall the standalone build, then re-auth — physical access to the machine means this is always available to me.

* * *

## TL;DR of what I actually did

1.  Standalone Tailscale on the mini, App Store version on the laptop, same account.
    
2.  Enabled Remote Login (plain SSH) + key-based auth on the mini.
    
3.  Turned on IP forwarding + LaunchDaemon to persist it.
    
4.  Advertised `192.168.x.0/24` and approved it in the console.
    
5.  Set `pmset autorestart 1`, made a conscious FileVault choice, kept the mini awake.
    
6.  *(Later / optional)* Enabled Tailnet Lock with both devices as signing nodes and stored the disablement secrets.
    

End result: I SSH to `mac-mini` and reach my whole home LAN from anywhere, no static IP, no port forwarding, encrypted end-to-end — and a blackout doesn't lock me out.
