# TailMux - macOS Login And Browser Procedure

Date: 2026-05-05

## Objective

Create separate TailMux profile identities on the same Mac, approve them in their respective tailnets, then route Safari and CLI traffic by profile-owned hostname suffix.

TailMux does not reuse the official Tailscale macOS app identity. The official app can stay installed and can be used for direct comparisons, but TailMux profile routing uses TailMux-managed identities.

## Recommended Profile Shape

Use `backend: "tsnet"` for new profiles:

```yaml
profiles:
  work:
    display_name: "Work tailnet"
    backend: "tsnet"
    hostname: "tailmux-work-macbook-pro"
    suffixes:
      - ".taild63bef.ts.net"
    match_root: true
    state_dir: "~/Library/Application Support/TailMux/tailnets/work"
    port: 0

  personal:
    display_name: "CQ Fabrication tailnet"
    backend: "tsnet"
    hostname: "tailmux-personal-macbook-pro"
    suffixes:
      - ".tail2c15f0.ts.net"
    match_root: true
    state_dir: "~/Library/Application Support/TailMux/tailnets/personal"
    port: 0
```

The hostname must be one DNS label: letters, numbers, and hyphens only. Avoid spaces, dots, underscores, and generated DHCP names.

Validate:

```bash
tailmux config validate
```

## Start TailMux

```bash
tailmux up
```

This starts:

- embedded `tsnet` profiles
- local router on `127.0.0.1:43100`
- PAC endpoint on `127.0.0.1:43180/proxy.pac`

Keep the terminal open unless TailMux is started by a future launchd service.

## First Login

Run one profile at a time:

```bash
tailmux profile login personal
tailmux profile status personal

tailmux profile login work
tailmux profile status work
```

When Tailscale prints an approval URL, open it and approve the device in the correct tailnet.

Expected device names:

```text
tailmux-personal-macbook-pro
tailmux-work-macbook-pro
```

## Clean Re-Login

For embedded `tsnet`, `--reset` is not supported. Use:

```bash
tailmux profile logout personal
tailmux profile login personal
```

If development state is broken and the tailnet admin entry can be recreated, stop TailMux and rotate only that profile state directory. Do not delete the other profile state.

External `backend: "tailscaled"` profiles still support the Tailscale CLI reset flow:

```bash
tailmux profile logout work
tailmux profile login work --reset
```

Use `--reset` only with the external backend.

## UDP Ports

For embedded `tsnet`, keep `port: 0` unless you are deliberately debugging firewall or NAT behavior. This lets Tailscale select an available UDP port and avoids fixed-port collisions with other local networking tools.

For the compatibility `backend: "tailscaled"` path, fixed unique ports are still useful:

```yaml
profiles:
  work:
    port: 41651
  personal:
    port: 41652
```

Avoid the official app's usual `41641` port.

## Safari PAC Setup

TailMux serves:

```text
http://127.0.0.1:43180/proxy.pac
```

In macOS System Settings:

1. Open Network.
2. Select the active service, such as Wi-Fi or Ethernet.
3. Open Details.
4. Open Proxies.
5. Enable Automatic Proxy Configuration.
6. Paste the PAC URL above.
7. Apply.

Expected behavior:

```text
http://claudios-mac-mini-1.tail2c15f0.ts.net:13200 -> TailMux -> personal
http://banihashemi-mac.taild63bef.ts.net:8888      -> TailMux -> work
https://google.com                                  -> DIRECT
```

If Safari fails but another browser works, verify Safari is using the active network service PAC. The Codex in-app browser is not proof that Safari is configured.

The menu bar app manages the macOS PAC lifecycle automatically:

- On launch, it enables TailMux's PAC on active network services when the service has no PAC or already points to TailMux.
- It never overwrites a non-TailMux PAC URL.
- On quit, it disables only PAC settings whose URL points to TailMux.

## CLI Proxy Setup

For HTTP tools:

```bash
HTTPS_PROXY=http://127.0.0.1:43100 curl http://claudios-mac-mini-1.tail2c15f0.ts.net:13200/live-auctions
```

Or:

```bash
eval "$(tailmux env)"
```

For SSH:

```sshconfig
Host *.taild63bef.ts.net
  ProxyCommand tailmux connect %h %p

Host *.tail2c15f0.ts.net
  ProxyCommand tailmux connect %h %p
```

## Diagnose Routing

```bash
tailmux test claudios-mac-mini-1.tail2c15f0.ts.net
tailmux diag path http://claudios-mac-mini-1.tail2c15f0.ts.net:13200/live-auctions --netcheck
```

Read the output in this order:

1. `profile`: confirms suffix ownership.
2. `status`: confirms profile backend state and peer visibility.
3. `ping`: confirms direct, DERP, relay, or missing peer.
4. `http`: confirms router timing for HTTP/HTTPS targets.
5. `recommendations`: gives next action.

## Diagnose Performance

Repeated page fetch:

```bash
tailmux diag fetch \
  --modes router,embedded,direct \
  --samples 5 \
  --timeout 25s \
  --read-limit 4194304 \
  http://claudios-mac-mini-1.tail2c15f0.ts.net:13200/live-auctions
```

SSE first event:

```bash
tailmux diag fetch \
  --modes router,direct \
  --samples 5 \
  --first-byte-only \
  http://claudios-mac-mini-1.tail2c15f0.ts.net:13200/events/stream
```

Direct mode is meaningful only when the official Tailscale app is currently connected to the same tailnet as the target URL.

## Tailscale CLI Version Alignment

If `tailscale status` warns about CLI/server mismatch, use the app-bundled CLI as the authoritative binary for the official app:

```bash
/Applications/Tailscale.app/Contents/MacOS/Tailscale version
```

On Claudio's Mac, `/opt/homebrew/bin/tailscale` was converted to a wrapper for the app-bundled CLI and the old Homebrew symlink was backed up as:

```text
/opt/homebrew/bin/tailscale.homebrew-1.96.4.bak
```

This affects official-client diagnostics only. TailMux embedded `tsnet` uses the Go module dependency.

## Stop TailMux

Foreground:

```text
Ctrl-C
```

If running in the development tmux session:

```bash
tmux kill-session -t tailmuxd
```

Verify:

```bash
lsof -nP -iTCP:43100 -iTCP:43180
pgrep -fl tailmux
networksetup -getautoproxyurl Wi-Fi
```

The process checks should show no TailMux router/PAC process when stopped.

The active network service should not keep TailMux's PAC enabled while TailMux is stopped. If the PAC URL is still `http://127.0.0.1:43180/proxy.pac` and `Enabled: Yes`, disable it before testing unrelated apps:

```bash
networksetup -setautoproxystate Wi-Fi off
```
