diff --git a/src/components/NavigationDocs.jsx b/src/components/NavigationDocs.jsx
index ec5e1b429..16420a04a 100644
--- a/src/components/NavigationDocs.jsx
+++ b/src/components/NavigationDocs.jsx
@@ -461,6 +461,10 @@ export const docsNavigation = [
title: 'MDM for Deployment',
isOpen: true,
links: [
+ {
+ title: 'macOS CLI-Only .pkg',
+ href: '/manage/integrations/mdm-deployment/macos-cli-pkg-deployment',
+ },
{
title: 'Deploy with Jamf Pro',
href: '/manage/integrations/mdm-deployment/jamf-pro-netbird-integration',
diff --git a/src/pages/get-started/install/macos.mdx b/src/pages/get-started/install/macos.mdx
index 8f8b7f57f..c838a84ac 100644
--- a/src/pages/get-started/install/macos.mdx
+++ b/src/pages/get-started/install/macos.mdx
@@ -1,4 +1,4 @@
-import {Note} from "@/components/mdx";
+import {Note, Warning} from "@/components/mdx";
# MacOS Installation
@@ -10,6 +10,8 @@ The NetBird client (agent) allows a peer to join a pre-existing NetBird deployme
curl -fsSL https://pkgs.netbird.io/install.sh | sh
```
+This installs the full NetBird application, including the desktop UI and the daemon service.
+
### Package install
1. Download the latest MacOS release installer for your [processor](https://support.apple.com/en-us/HT211814 ):
@@ -47,41 +49,66 @@ brew unlink netbird
sudo netbird service start
```
-### Binary Install
-**Installation from binary (CLI only)**
+### CLI-only install (binary)
+
+If you need only the CLI client without the desktop UI — for example, on headless servers or for MDM/fleet deployments — you can install the standalone binary directly.
+
+#### One-command binary install
+
+
+ The macOS binary tarballs from GitHub releases are **not Apple code-signed or notarized**. Only the official `.pkg` installer from [pkgs.netbird.io](https://pkgs.netbird.io) contains signed binaries. The unsigned binary will trigger Gatekeeper warnings and may be blocked by MDM policies. For managed fleet deployments, see [Building a CLI-Only .pkg for MDM Deployment](/manage/integrations/mdm-deployment/macos-cli-pkg-deployment) which includes steps for signing the binary with your own Developer ID.
+
+
+The install script supports a binary-only mode that downloads the tarball, extracts the `netbird` binary to `/usr/local/bin/`, and registers the launchd daemon:
-1. Checkout NetBird [releases](https://github.com/netbirdio/netbird/releases/latest)
-2. Download the latest release:
```bash
- curl -L -o ./netbird_.tar.gz https://github.com/netbirdio/netbird/releases/download/v/netbird___.tar.gz
+curl -fsSL https://pkgs.netbird.io/install.sh | USE_BIN_INSTALL=true SKIP_UI_APP=true sh
```
-
+To update an existing binary install, add the `UPDATE_NETBIRD` flag:
- You need to replace some variables from the URL above:
+```bash
+curl -fsSL https://pkgs.netbird.io/install.sh | USE_BIN_INSTALL=true SKIP_UI_APP=true UPDATE_NETBIRD=true sh
+```
- - Replace **VERSION** with the latest released version.
- - Replace **OS** with "linux", "darwin" for MacOS or "windows"
- - Replace **Arch** with your target system CPU architecture
+#### Manual binary install
+1. Checkout NetBird [releases](https://github.com/netbirdio/netbird/releases/latest)
+2. Download the latest release for macOS:
+```bash
+ # For Apple Silicon (M1, M2, M3, M4):
+ curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v/netbird__darwin_arm64.tar.gz
+
+ # For Intel:
+ curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v/netbird__darwin_amd64.tar.gz
+
+ # Universal binary (works on both architectures):
+ curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v/netbird__darwin_all.tar.gz
+```
+
+
+ Replace **VERSION** with the latest released version (e.g., `0.36.5`). You can find version numbers on the [releases page](https://github.com/netbirdio/netbird/releases/latest).
-3. Decompress
+3. Extract and install the binary:
```bash
- tar xzf ./netbird_.tar.gz
- sudo mv netbird /usr/bin/netbird
- sudo chown root:root /usr/bin/netbird
- sudo chmod +x /usr/bin/netbird
+ tar xzf ./netbird.tar.gz
+ sudo mv netbird /usr/local/bin/netbird
+ sudo chown root:wheel /usr/local/bin/netbird
+ sudo chmod +x /usr/local/bin/netbird
```
-After that you may need to add /usr/bin in your PATH environment variable:
-````bash
- export PATH=$PATH:/usr/bin
-````
-4. Install and run the service
+4. Install and start the daemon service:
```bash
sudo netbird service install
sudo netbird service start
```
+
+This creates a launchd daemon at `/Library/LaunchDaemons/netbird.plist` that runs as root (required for managing the WireGuard network interface).
+
+
+ Automatic updates via the NetBird dashboard do **not** work for binary-only installs. The auto-updater requires the official `.pkg` installer (it checks for the `io.netbird.client` package receipt). For binary installs, you must update manually or push updates through your MDM solution. See [Building a CLI-Only .pkg for MDM Deployment](/manage/integrations/mdm-deployment/macos-cli-pkg-deployment) for a managed approach.
+
+
## Running NetBird with SSO Login
### Desktop UI Application
If you installed the Desktop UI client, you can launch it and click on Connect.
diff --git a/src/pages/manage/integrations/mdm-deployment/macos-cli-pkg-deployment.mdx b/src/pages/manage/integrations/mdm-deployment/macos-cli-pkg-deployment.mdx
new file mode 100644
index 000000000..25b9b25ba
--- /dev/null
+++ b/src/pages/manage/integrations/mdm-deployment/macos-cli-pkg-deployment.mdx
@@ -0,0 +1,388 @@
+import {Note, Warning} from "@/components/mdx";
+
+# Building a CLI-Only .pkg for macOS MDM Deployment
+
+When deploying NetBird across a fleet of macOS devices using an MDM solution (Jamf Pro, Kandji, Munki, etc.), you may want a headless, CLI-only installation without the desktop UI. The official `.pkg` from [pkgs.netbird.io](https://pkgs.netbird.io) bundles the full NetBird.app, which includes the menu bar UI. This guide shows you how to build a custom `.pkg` that installs only the `netbird` CLI binary and registers it as a launchd daemon.
+
+This approach is useful when:
+
+* You are deploying to headless servers or CI/CD runners that have no user session
+* You want to minimize the footprint on managed endpoints
+* Your MDM workflow requires a `.pkg` artifact (rather than a raw binary or install script)
+* You need to control exactly which version is deployed across your fleet
+
+## Prerequisites
+
+* A Mac with `pkgbuild` available (included with Xcode Command Line Tools)
+* Access to your MDM solution with permissions to upload packages and create deployment policies
+* A NetBird [setup key](/manage/peers/register-machines-using-setup-keys) for initial enrollment (reusable keys are recommended for fleet deployments)
+
+## How the CLI-only install works
+
+The standard NetBird `.pkg` installer places `NetBird.app` into `/Applications` and symlinks the binary to `/usr/local/bin/netbird`. A CLI-only install skips the app bundle entirely and places the `netbird` binary directly in `/usr/local/bin/`.
+
+When you run `netbird service install`, it creates a launchd daemon plist at `/Library/LaunchDaemons/netbird.plist`. The service runs as root, which is required for creating and managing the WireGuard network interface (`utun` device).
+
+
+ The NetBird daemon stores its configuration in `/var/lib/netbird/` by default. Once a peer is enrolled (via SSO or setup key), the configuration persists across reinstalls. Subsequent package updates only need to restart the service — no re-enrollment is required.
+
+
+## Step 1: Download the CLI binary
+
+Download the appropriate tarball from the [NetBird GitHub releases](https://github.com/netbirdio/netbird/releases/latest) page. Each release publishes architecture-specific and universal macOS binaries:
+
+```bash
+# Set the version you want to deploy
+VERSION="0.36.5"
+
+# Universal binary (recommended — works on both Intel and Apple Silicon):
+curl -L -o netbird.tar.gz \
+ "https://github.com/netbirdio/netbird/releases/download/v${VERSION}/netbird_${VERSION}_darwin_all.tar.gz"
+
+# Or architecture-specific:
+# Apple Silicon: netbird_${VERSION}_darwin_arm64.tar.gz
+# Intel: netbird_${VERSION}_darwin_amd64.tar.gz
+```
+
+Extract the binary:
+
+```bash
+mkdir -p pkg-root/usr/local/bin
+tar xzf netbird.tar.gz -C pkg-root/usr/local/bin netbird
+chmod +x pkg-root/usr/local/bin/netbird
+```
+
+
+ The macOS binary tarballs from GitHub releases are **not Apple code-signed or notarized**. Only the official `.pkg` installer from [pkgs.netbird.io](https://pkgs.netbird.io) contains signed binaries. For MDM deployments, you should sign the binary with your own Developer ID Application certificate before packaging — see [Step 3](#step-3-build-the-pkg) for instructions.
+
+
+## Step 2: Create install scripts
+
+Create a `scripts/` directory with preinstall and postinstall scripts. These handle stopping any existing service before the upgrade and starting it after.
+
+```bash
+mkdir -p scripts
+```
+
+### Preinstall script
+
+The preinstall script stops any running NetBird service to allow the binary to be replaced cleanly:
+
+```bash
+cat > scripts/preinstall << 'PREINSTALL'
+#!/bin/sh
+
+LOG_FILE=/var/log/netbird/client_pre_install.log
+AGENT=/usr/local/bin/netbird
+
+mkdir -p /var/log/netbird/
+
+{
+ echo "=== NetBird CLI preinstall: $(date) ==="
+
+ # Check if netbird was installed with Homebrew
+ if command -v brew >/dev/null 2>&1; then
+ if brew list --formula 2>/dev/null | grep -q netbird; then
+ echo "NetBird was installed with Homebrew. Please use Homebrew to manage the package."
+ exit 1
+ fi
+ fi
+
+ # Stop the running service if it exists
+ if [ -f "$AGENT" ]; then
+ $AGENT service stop 2>/dev/null || true
+ fi
+
+ echo "Preinstall complete"
+ exit 0
+} >> "$LOG_FILE" 2>&1
+PREINSTALL
+
+chmod +x scripts/preinstall
+```
+
+### Postinstall script
+
+The postinstall script installs the launchd daemon service and optionally enrolls the peer with a setup key on first install:
+
+```bash
+cat > scripts/postinstall << 'POSTINSTALL'
+#!/bin/sh
+
+LOG_FILE=/var/log/netbird/client_post_install.log
+AGENT=/usr/local/bin/netbird
+
+mkdir -p /var/log/netbird/
+
+{
+ echo "=== NetBird CLI postinstall: $(date) ==="
+
+ # Install and start the daemon service
+ $AGENT service install 2>/dev/null || true
+ $AGENT service start || {
+ echo "ERROR: Failed to start NetBird service"
+ exit 1
+ }
+
+ # Enroll the peer if not already configured.
+ # The config file exists once the peer has been enrolled at least once.
+ CONFIG_FILE="/var/lib/netbird/config.json"
+ if [ ! -f "$CONFIG_FILE" ]; then
+ echo "First install detected — enrolling with setup key"
+ # Replace YOUR_SETUP_KEY with your actual reusable setup key.
+ # For self-hosted deployments, add: --management-url https://your-management.example.com
+ $AGENT up --setup-key YOUR_SETUP_KEY
+ else
+ echo "Existing configuration found — skipping enrollment"
+ fi
+
+ echo "Postinstall complete"
+ exit 0
+} >> "$LOG_FILE" 2>&1
+POSTINSTALL
+
+chmod +x scripts/postinstall
+```
+
+
+ Replace `YOUR_SETUP_KEY` with an actual [reusable setup key](/manage/peers/register-machines-using-setup-keys) from your NetBird dashboard. For self-hosted deployments, also add the `--management-url` flag. Do not commit setup keys to version control — consider injecting them at build time via your CI/CD pipeline or MDM variables.
+
+
+
+ On subsequent installs (updates), the postinstall script detects the existing configuration and skips enrollment. It only restarts the service so the new binary takes effect.
+
+
+## Step 3: Sign the binary and build the .pkg
+
+The binary from the tarball is unsigned. For MDM deployment, you should sign both the binary (with `codesign`) and the installer package (with `pkgbuild --sign`). These are separate signing steps that use different certificate types.
+
+### Sign the binary
+
+Use your Developer ID Application certificate to code-sign the binary before packaging:
+
+```bash
+codesign --sign "Developer ID Application: Your Organization (TEAMID)" \
+ --options runtime \
+ --timestamp \
+ --force \
+ pkg-root/usr/local/bin/netbird
+```
+
+The `--options runtime` flag enables the hardened runtime (required for notarization), and `--timestamp` embeds a secure timestamp from Apple's servers.
+
+### Build the .pkg
+
+Use `pkgbuild` to assemble the signed binary and scripts into an installer package:
+
+```bash
+pkgbuild \
+ --root pkg-root \
+ --scripts scripts \
+ --identifier com.your-org.netbird-cli \
+ --version "${VERSION}" \
+ --install-location / \
+ --sign "Developer ID Installer: Your Organization (TEAMID)" \
+ netbird-cli-${VERSION}.pkg
+```
+
+
+ Use a custom package identifier (e.g., `com.your-org.netbird-cli`) rather than `io.netbird.client`. The official identifier is used by the NetBird auto-updater to detect managed installs. Using it for your custom package could cause conflicts if the auto-updater is enabled on your NetBird dashboard.
+
+
+
+ Binary signing uses a **Developer ID Application** certificate (`codesign`), while package signing uses a **Developer ID Installer** certificate (`pkgbuild --sign`). These are different certificates — you need both for a fully signed deployment. See [Apple's documentation](https://developer.apple.com/help/account/create-certificates/create-developer-id-certificates/) for details.
+
+
+### Optional: Notarize the .pkg
+
+For full Gatekeeper compatibility, submit the signed `.pkg` to Apple for notarization:
+
+```bash
+xcrun notarytool submit netbird-cli-${VERSION}.pkg \
+ --apple-id "your@email.com" \
+ --team-id "TEAMID" \
+ --password "app-specific-password" \
+ --wait
+
+# Staple the notarization ticket to the package
+xcrun stapler staple netbird-cli-${VERSION}.pkg
+```
+
+## Step 4: Deploy via MDM
+
+Upload the `.pkg` to your MDM solution and create a deployment policy. The exact steps vary by platform:
+
+* **Jamf Pro**: Upload the package under `Settings > Computer Management > Packages`, then create a policy with appropriate triggers (enrollment, recurring check-in). See [Deploying NetBird with Jamf Pro](/manage/integrations/mdm-deployment/jamf-pro-netbird-integration) for detailed instructions.
+* **Kandji**: Create a Custom App library item with the `Installer Package` option. See [Deploying NetBird with Kandji](/manage/integrations/mdm-deployment/kandji-netbird-integration) for detailed instructions.
+* **Munki**: Import the `.pkg` into your Munki repository using `munkiimport` and assign it to the appropriate manifest.
+* **Microsoft Intune**: Upload as a macOS LOB app. See [Deploying NetBird with Intune](/manage/integrations/mdm-deployment/intune-netbird-integration) for detailed instructions.
+
+## Managing updates
+
+Because the CLI-only install does not have the `io.netbird.client` package receipt, the NetBird [automatic update](/manage/peers/auto-update) feature does not work for these deployments. You must manage updates through one of these approaches:
+
+### Push updated .pkg via MDM
+
+Build a new `.pkg` with the updated binary (repeating Steps 1-3) and deploy it through your MDM. The preinstall script stops the running service, the new binary replaces the old one, and the postinstall script restarts the service. No re-enrollment is needed.
+
+### Use the install script with UPDATE_NETBIRD
+
+For machines where you can run scripts remotely (via MDM script execution or SSH), use the install script's update mode:
+
+```bash
+curl -fsSL https://pkgs.netbird.io/install.sh | USE_BIN_INSTALL=true SKIP_UI_APP=true UPDATE_NETBIRD=true sh
+```
+
+This downloads the latest binary, replaces the existing one, and restarts the service.
+
+## Uninstalling
+
+To remove a CLI-only NetBird install:
+
+```bash
+sudo netbird down
+sudo netbird service stop
+sudo netbird service uninstall
+sudo rm /usr/local/bin/netbird
+sudo rm -rf /var/lib/netbird/
+sudo rm -rf /var/log/netbird/
+```
+
+You can wrap this in an MDM uninstall script or a preinstall script for a removal package.
+
+## Complete build script
+
+For convenience, here is a self-contained script that builds the CLI-only `.pkg`. It optionally signs the binary and package if signing identities are provided. Save it as `build-netbird-cli-pkg.sh`:
+
+```bash
+#!/bin/sh
+# Usage: ./build-netbird-cli-pkg.sh [MANAGEMENT_URL]
+#
+# Optional environment variables for signing:
+# APP_SIGN_ID - Developer ID Application identity (for binary signing)
+# PKG_SIGN_ID - Developer ID Installer identity (for package signing)
+# APPLE_ID - Apple ID email (for notarization)
+# APPLE_TEAM_ID - Apple Team ID (for notarization)
+# APPLE_APP_PWD - App-specific password (for notarization)
+#
+# Example (unsigned):
+# ./build-netbird-cli-pkg.sh 0.36.5 A1B2C3D4-E5F6-7890-ABCD-EF1234567890
+#
+# Example (signed + notarized):
+# APP_SIGN_ID="Developer ID Application: Acme Inc (TEAMID)" \
+# PKG_SIGN_ID="Developer ID Installer: Acme Inc (TEAMID)" \
+# APPLE_ID="dev@acme.com" APPLE_TEAM_ID="TEAMID" APPLE_APP_PWD="xxxx-xxxx-xxxx-xxxx" \
+# ./build-netbird-cli-pkg.sh 0.36.5 A1B2C3D4-E5F6-7890-ABCD-EF1234567890
+
+set -e
+
+VERSION="${1:?Usage: $0 [MANAGEMENT_URL]}"
+SETUP_KEY="${2:?Usage: $0 [MANAGEMENT_URL]}"
+MANAGEMENT_URL="${3:-}"
+PKG_ID="com.your-org.netbird-cli"
+WORK_DIR=$(mktemp -d)
+
+echo "Building NetBird CLI .pkg v${VERSION}..."
+
+# Download and extract
+curl -fSL -o "${WORK_DIR}/netbird.tar.gz" \
+ "https://github.com/netbirdio/netbird/releases/download/v${VERSION}/netbird_${VERSION}_darwin_all.tar.gz"
+mkdir -p "${WORK_DIR}/root/usr/local/bin"
+tar xzf "${WORK_DIR}/netbird.tar.gz" -C "${WORK_DIR}/root/usr/local/bin" netbird
+chmod +x "${WORK_DIR}/root/usr/local/bin/netbird"
+
+# Sign the binary if a signing identity is provided
+if [ -n "${APP_SIGN_ID:-}" ]; then
+ echo "Signing binary with: ${APP_SIGN_ID}"
+ codesign --sign "${APP_SIGN_ID}" \
+ --options runtime \
+ --timestamp \
+ --force \
+ "${WORK_DIR}/root/usr/local/bin/netbird"
+else
+ echo "WARNING: No APP_SIGN_ID set — binary will be unsigned."
+ echo "Unsigned binaries trigger Gatekeeper warnings and may be blocked by MDM policies."
+fi
+
+# Build management URL flag
+MGMT_FLAG=""
+if [ -n "$MANAGEMENT_URL" ]; then
+ MGMT_FLAG="--management-url ${MANAGEMENT_URL}"
+fi
+
+# Create scripts
+mkdir -p "${WORK_DIR}/scripts"
+
+cat > "${WORK_DIR}/scripts/preinstall" << 'EOF'
+#!/bin/sh
+AGENT=/usr/local/bin/netbird
+mkdir -p /var/log/netbird/
+{
+ echo "=== NetBird CLI preinstall: $(date) ==="
+ if command -v brew >/dev/null 2>&1; then
+ if brew list --formula 2>/dev/null | grep -q netbird; then
+ echo "NetBird installed via Homebrew. Aborting."
+ exit 1
+ fi
+ fi
+ [ -f "$AGENT" ] && $AGENT service stop 2>/dev/null || true
+ echo "Preinstall complete"
+ exit 0
+} >> /var/log/netbird/client_pre_install.log 2>&1
+EOF
+
+cat > "${WORK_DIR}/scripts/postinstall" << EOF
+#!/bin/sh
+AGENT=/usr/local/bin/netbird
+mkdir -p /var/log/netbird/
+{
+ echo "=== NetBird CLI postinstall: \$(date) ==="
+ \$AGENT service install 2>/dev/null || true
+ \$AGENT service start || { echo "ERROR: Failed to start service"; exit 1; }
+ if [ ! -f "/var/lib/netbird/config.json" ]; then
+ echo "First install — enrolling with setup key"
+ \$AGENT up --setup-key ${SETUP_KEY} ${MGMT_FLAG}
+ else
+ echo "Existing config found — skipping enrollment"
+ fi
+ echo "Postinstall complete"
+ exit 0
+} >> /var/log/netbird/client_post_install.log 2>&1
+EOF
+
+chmod +x "${WORK_DIR}/scripts/preinstall" "${WORK_DIR}/scripts/postinstall"
+
+# Build the package
+PKG_SIGN_FLAGS=""
+if [ -n "${PKG_SIGN_ID:-}" ]; then
+ echo "Signing package with: ${PKG_SIGN_ID}"
+ PKG_SIGN_FLAGS="--sign ${PKG_SIGN_ID}"
+fi
+
+pkgbuild \
+ --root "${WORK_DIR}/root" \
+ --scripts "${WORK_DIR}/scripts" \
+ --identifier "${PKG_ID}" \
+ --version "${VERSION}" \
+ --install-location / \
+ ${PKG_SIGN_FLAGS} \
+ "netbird-cli-${VERSION}.pkg"
+
+# Notarize if credentials are provided
+if [ -n "${APPLE_ID:-}" ] && [ -n "${APPLE_TEAM_ID:-}" ] && [ -n "${APPLE_APP_PWD:-}" ]; then
+ echo "Submitting for notarization..."
+ xcrun notarytool submit "netbird-cli-${VERSION}.pkg" \
+ --apple-id "${APPLE_ID}" \
+ --team-id "${APPLE_TEAM_ID}" \
+ --password "${APPLE_APP_PWD}" \
+ --wait
+ xcrun stapler staple "netbird-cli-${VERSION}.pkg"
+ echo "Notarization complete."
+fi
+
+# Clean up
+rm -rf "${WORK_DIR}"
+
+echo "Built: netbird-cli-${VERSION}.pkg"
+echo "Upload this package to your MDM solution for deployment."
+```