mirror of
https://github.com/netbirdio/docs.git
synced 2026-08-25 01:01:27 +02:00
Merge remote-tracking branch 'origin/main' into docs/posture-checks-mobile-support
# Conflicts: # src/pages/manage/access-control/posture-checks/index.mdx
This commit is contained in:
@@ -23,7 +23,7 @@ const nextConfig = {
|
||||
return [
|
||||
{
|
||||
source: '/slack-url',
|
||||
destination: 'https://join.slack.com/t/netbirdio/shared_invite/zt-3rxbnuiyt-vXZxZ6UCjJ8aQLNLXMBJxQ',
|
||||
destination: 'https://join.slack.com/t/netbirdio/shared_invite/zt-3wwkb0b9y-opbG_pFSoOgP41KUV00MtA',
|
||||
permanent: false,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://pkgs.netbird.io/install.sh | USE_BIN_INSTALL=true SKIP_UI_APP=true UPDATE_NETBIRD=true sh
|
||||
```
|
||||
|
||||
#### Manual binary install
|
||||
|
||||
1. Checkout NetBird [releases](https://github.com/netbirdio/netbird/releases/latest)
|
||||
2. Download the latest release:
|
||||
2. Download the latest release for macOS:
|
||||
```bash
|
||||
curl -L -o ./netbird_<VERSION>.tar.gz https://github.com/netbirdio/netbird/releases/download/v<VERSION>/netbird_<VERSION>_<OS>_<Arch>.tar.gz
|
||||
# For Apple Silicon (M1, M2, M3, M4):
|
||||
curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v<VERSION>/netbird_<VERSION>_darwin_arm64.tar.gz
|
||||
|
||||
# For Intel:
|
||||
curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v<VERSION>/netbird_<VERSION>_darwin_amd64.tar.gz
|
||||
|
||||
# Universal binary (works on both architectures):
|
||||
curl -L -o ./netbird.tar.gz https://github.com/netbirdio/netbird/releases/download/v<VERSION>/netbird_<VERSION>_darwin_all.tar.gz
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
You need to replace some variables from the URL above:
|
||||
|
||||
- Replace **VERSION** with the latest released version.
|
||||
- Replace **OS** with "linux", "darwin" for MacOS or "windows"
|
||||
- Replace **Arch** with your target system CPU architecture
|
||||
|
||||
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).
|
||||
</Note>
|
||||
|
||||
3. Decompress
|
||||
3. Extract and install the binary:
|
||||
```bash
|
||||
tar xzf ./netbird_<VERSION>.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).
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
## Running NetBird with SSO Login
|
||||
### Desktop UI Application
|
||||
If you installed the Desktop UI client, you can launch it and click on Connect.
|
||||
|
||||
@@ -460,12 +460,12 @@ echo $response;
|
||||
<Property name="peer_network_range_check" type="object" required={false}>
|
||||
|
||||
<details className="custom-details" open>
|
||||
<summary>Posture check for allow or deny access based on peer local network addresses</summary>
|
||||
<summary>Posture check for allow or deny access based on the peer's IP addresses. A range matches when it contains any of the peer's local network interface IPs or its public connection (NAT egress) IP, so ranges may target private subnets, public CIDRs, or single hosts via a /32 or /128.</summary>
|
||||
<Properties>
|
||||
|
||||
<Properties><Property name="ranges" type="string[]" required={true}>
|
||||
|
||||
List of peer network ranges in CIDR notation
|
||||
List of network ranges in CIDR notation, matched against the peer's local interface IPs and its public connection IP
|
||||
|
||||
</Property>
|
||||
<Property name="action" type="string" required={true} enumList={["allow","deny"]}>
|
||||
@@ -1636,12 +1636,12 @@ echo $response;
|
||||
<Property name="peer_network_range_check" type="object" required={false}>
|
||||
|
||||
<details className="custom-details" open>
|
||||
<summary>Posture check for allow or deny access based on peer local network addresses</summary>
|
||||
<summary>Posture check for allow or deny access based on the peer's IP addresses. A range matches when it contains any of the peer's local network interface IPs or its public connection (NAT egress) IP, so ranges may target private subnets, public CIDRs, or single hosts via a /32 or /128.</summary>
|
||||
<Properties>
|
||||
|
||||
<Properties><Property name="ranges" type="string[]" required={true}>
|
||||
|
||||
List of peer network ranges in CIDR notation
|
||||
List of network ranges in CIDR notation, matched against the peer's local interface IPs and its public connection IP
|
||||
|
||||
</Property>
|
||||
<Property name="action" type="string" required={true} enumList={["allow","deny"]}>
|
||||
|
||||
@@ -96,4 +96,26 @@ When we are connected from inside the office, we can observe that the NetBird ro
|
||||
Notice that subnet `192.168.1.0/24` is routed through our Wireguard interface (`utun100`).
|
||||
|
||||
As you can see, the Posture Check is working as expected, and the traffic is being routed through NetBird only when the client is outside the office network.
|
||||
|
||||
## Matching by office public IP
|
||||
The example above relies on the office LAN subnet showing up on the peer's local network interface. In some deployments this isn't practical — for example, when the office hands out an opaque DHCP range that overlaps with common home-network subnets, or when peers connect through a guest network that doesn't expose the production LAN on the device.
|
||||
|
||||
In these cases you can match the peer's **public egress IP** instead — the source IP the NetBird management server observes when the peer connects. The Peer Network Range posture check evaluates this IP automatically against any range in the list and matches when the IP is contained in the range, so you can use a single-host prefix for one address or a CIDR for a whole block.
|
||||
|
||||
### IPv4 example
|
||||
If your office's public IPv4 address is `203.0.113.10`, create a Peer Network Range posture check with the `Block` action and add `203.0.113.10/32` to the list. Peers connecting from that egress IP will be blocked from the route, while peers connecting from anywhere else will reach it.
|
||||
|
||||
If your office (or your ISP) hands out an entire public block, you can add the block directly — for example `1.0.0.0/24` or `3.0.0.0/23`. Any peer whose connection IP falls in that range will match.
|
||||
|
||||
### IPv6 example
|
||||
If your office also (or only) has an IPv6 egress, add the address as a `/128`, for example `2001:db8::1/128`, or a wider IPv6 prefix such as `2001:db8::/48`. You can include IPv4 and IPv6 entries in the same posture check; a peer matches if its connection IP falls into any of them.
|
||||
|
||||
<Note>
|
||||
For this to work, the NetBird management server must see the peer's real source IP. When running self-hosted behind a reverse proxy or load balancer, ensure the proxy is configured to forward the client IP (PROXY protocol or `X-Forwarded-For`). The country and city shown on the peer in the dashboard are a quick sanity check — if they reflect your proxy's datacenter rather than the peer's actual location, the source IP isn't being forwarded correctly.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Mobile peers connecting through cellular networks normally have a different egress IP than your office, so they will not be matched. However, if a phone joins the office Wi-Fi, its egress IP becomes the office IP and the block will apply — usually the desired behavior.
|
||||
</Note>
|
||||
|
||||
This concludes this Posture Check example.
|
||||
|
||||
@@ -41,6 +41,23 @@ This posture check lets you precisely control network access by specifying which
|
||||
|
||||

|
||||
|
||||
The check evaluates a peer against two sources of address information:
|
||||
|
||||
- **The peer's local network interfaces** — the IP addresses configured on the device's NICs (e.g. the office LAN `192.168.1.0/24` the device is plugged into).
|
||||
- **The peer's public connection IP** — the source IP the NetBird management server observes when the peer connects (i.e. the egress / NAT'd IP).
|
||||
|
||||
A configured range matches when it contains any of these addresses, so the same check covers both private subnets and public CIDRs. Both IPv4 and IPv6 are supported. A few examples:
|
||||
|
||||
- Block a single office public IPv4: `203.0.113.10/32`
|
||||
- Allow a public ISP/office block: `1.0.0.0/24` or `3.0.0.0/23`
|
||||
- Block an entire private network: `192.168.1.0/24`
|
||||
- Block a single IPv6 host: `2001:db8::1/128`
|
||||
- Block an IPv6 prefix: `2001:db8::/48`
|
||||
|
||||
<Note>
|
||||
Matching against the public connection IP requires the management server to see the peer's real source IP. If NetBird sits behind a reverse proxy or load balancer, ensure the proxy forwards the client IP (e.g. via the PROXY protocol or `X-Forwarded-For`); otherwise the check will only see the proxy's IP. A quick sanity check: the country and city resolved on the peer in the dashboard should reflect the peer's actual location, not your proxy's.
|
||||
</Note>
|
||||
|
||||
### Operating System
|
||||
Restrict access based on the connecting device's OS, ensuring only approved and potentially more secure operating systems can connect.
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
<Note>
|
||||
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.
|
||||
</Note>
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
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.
|
||||
</Note>
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
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.
|
||||
</Note>
|
||||
|
||||
### 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 <VERSION> <SETUP_KEY> [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 <VERSION> <SETUP_KEY> [MANAGEMENT_URL]}"
|
||||
SETUP_KEY="${2:?Usage: $0 <VERSION> <SETUP_KEY> [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."
|
||||
```
|
||||
@@ -344,7 +344,7 @@ Recommended posture checks per policy:
|
||||
- Require your EDR (Endpoint Detection and Response) or RMM (Remote Monitoring and Management) agent process to be running before granting access to sensitive resources. This ensures security tools are active on the device.
|
||||
|
||||
<Note>
|
||||
The **Peer Network Range (CIDR)** posture check is not supported on iOS and Android. If you need location-based restrictions for mobile clients, consider using the **Geolocation** posture check as an alternative.
|
||||
On iOS and Android, the **Peer Network Range (CIDR)** posture check cannot evaluate the device's local network interfaces, so ranges intended to match local LANs (e.g. `192.168.1.0/24`) will not match. Ranges that target the peer's **public connection IP** (e.g. `203.0.113.10/32` or a public CIDR like `1.0.0.0/24`) still work on mobile, because the management server observes that source IP itself. For mobile-only deployments that need country-level restrictions, **Geolocation** remains a good alternative.
|
||||
</Note>
|
||||
|
||||
Example posture combinations:
|
||||
|
||||
Reference in New Issue
Block a user