# VeloraMesh macOS Client Install

Run these commands from this extracted package.

## Easiest Interactive Install

```bash
sudo bash ./install-macos-client.sh
```

The installer opens a guided menu when no advanced parameters are supplied:

```text
1) Guided install/update
2) Network operations
3) Service operations
4) Fresh install/reset client
5) Uninstall LaunchDaemon, keep files/config
6) Purge client install and config
0) Exit
```

`Guided install/update` asks for API host/domain, API HTTPS port, network name, device name, network join secret, edge discovery host/domain, edge UDP port, and whether the background tunnel service should be installed.

Join secrets entered through the installer must be 24-256 characters. Short or overlong secrets are rejected locally before a control-plane join request is sent.

`Network operations` can join, leave, connect/disconnect, list peers, rename the device, and run doctor without remembering client CLI commands.

`Service operations` can show LaunchDaemon status, start, stop, restart, and run doctor.

`Fresh install/reset client` removes the LaunchDaemon, installed files, and config before running the guided install flow.

The installer removes macOS quarantine attributes from installed files after copying them, which avoids Gatekeeper blocking binaries transferred through browser, Remote Desktop, or chat tools.

The installed LaunchDaemon sets `VELORAMESH_SECRET_DIR=/Library/Application Support/VeloraMesh/secrets`, keeping service private-key lookup independent from a login user's `HOME`.

Optional hardening: set `VELORAMESH_CONTROL_PLANE_SPKI_PIN` to `sha256/<base64-SHA256-SPKI>` before install and use `sudo -E` if you want the saved client config to pin the HTTPS control-plane certificate/public-key path.

## Install And Start Tunnel Service

```bash
printf '%s' '<network-join-secret>' > ./veloramesh-join.secret
chmod 600 ./veloramesh-join.secret
sudo bash ./install-macos-client.sh \
  --background \
  --replace-service \
  --status \
  --network-name home \
  --device-name "$(hostname)" \
  --join-secret-file ./veloramesh-join.secret \
  --discovery edge.veloramesh.com:3478
rm ./veloramesh-join.secret
```

## LAN Discovery Broadcasts

Direct IP access uses the peer's VeloraMesh virtual IP and does not need LAN browser discovery support.

For LAN server-browser tests, enable discovery from the Ubuntu server manager or admin CLI:

```bash
sudo /opt/veloramesh/veloramesh-server admin networks broadcast -network home -mode all
```

Return to the safer default after testing:

```bash
sudo /opt/veloramesh/veloramesh-server admin networks broadcast -network home -mode filtered
```

Custom local UDP ports/ranges can still be supplied for diagnostics with `--forward-broadcast-udp`, for example `2300-2400,6073`.

When the server administrator sets the network to `broadcast_mode=all`, local custom UDP port allowlists are not required for that network's UDP discovery broadcasts.

## Status

```bash
sudo launchctl print system/com.veloramesh.client
tail -n 100 /var/log/veloramesh-client.log
tail -n 100 /var/log/veloramesh-client.err.log
```

## Doctor

Run this after install to verify local identity, server auth, joined networks, peer visibility, MTU, and utun prerequisites:

```bash
sudo /opt/veloramesh/veloramesh-client doctor \
  -config "/Library/Application Support/VeloraMesh/client.json" \
  -network home
```

For a sanitized support bundle:

```bash
sudo /opt/veloramesh/veloramesh-client doctor \
  -config "/Library/Application Support/VeloraMesh/client.json" \
  -network home \
  -bundle /tmp/veloramesh-doctor.zip
```

The guided installer also runs a non-blocking doctor self-test after setup. LaunchDaemon stdout/stderr logs rotate at 5 MiB with five backups.

## Network Administration

Network creation, join-secret rotation, member removal, and device block/unblock are intentionally server-local operations. Use the Ubuntu server package's `manage-veloramesh-server.sh` menu or `/opt/veloramesh/veloramesh-server admin ...` on the server.

## Uninstall

Keep config and installed files:

```bash
sudo bash ./install-macos-client.sh --uninstall
```

Remove LaunchDaemon, installed files, and config:

```bash
sudo bash ./install-macos-client.sh --uninstall --purge
```

Fresh reset and guided reinstall:

```bash
sudo bash ./install-macos-client.sh --fresh
```