mirror of
https://github.com/netbirdio/docs.git
synced 2026-10-17 11:09:04 +02:00
docs: document the MDM keys added since the page was written, and iOS
The reference table listed 18 of the 23 keys the client recognises, and claimed a count of 16. Six keys were missing from every downloadable template as well, including lazyConnection, which the page already documented: - lazyConnection, disableAdvancedView, enableLocalMetrics, localMetricsAddress, allowRemoteJobs and debugBundleUploadURL are now in the reference table and in netbird.admx/.adml, io.netbird.client.plist, netbird-macos.mobileconfig, netbird-macos.sh and netbird-policy.reg. - Notes call out the two pairs that read as related but are not: disableMetricsCollection (anonymous telemetry) versus enableLocalMetrics (the client's own Prometheus endpoint), and disableAdvancedView being UI-only, so unlike its neighbours it never causes a request to be rejected. iOS and tvOS now have a section of their own. The channel is Apple's Managed App Configuration against bundle id io.netbird.app (io.netbird.app.tv on tvOS), with a new netbird-ios-appconfig.plist template and per-provider instructions. The section states what the policy reaches today: the app locks its interface and refuses configuration changes, while the tunnel engine runs in a Network Extension that does not receive the app configuration, so keys the engine applies to the connection are not enforced there yet. Two template defects found on the way: - netbird-macos.mobileconfig was not well-formed XML. Its header comment contained a double hyphen, which XML forbids inside a comment, so plutil -lint and any strict parser rejected the file an admin downloaded. - netbird-policy.reg had one LF-terminated line among CRLF ones; normalised, with the UTF-16LE encoding reg import requires preserved. Verified with npm run build and npm run lint:mdx, plus XML well-formedness on all five XML templates, bash -n on the shell template, and a cross-reference check that every string and presentation the ADMX references is defined in the ADML.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Note, Warning } from "@/components/mdx";
|
||||
|
||||
export const description =
|
||||
"Enforce NetBird client configuration through your MDM channel (Intune, Jamf, Kandji, Mosyle, Workspace ONE, JumpCloud, Group Policy). Push management URL, kill switches, and other settings to a fleet of Windows and macOS devices.";
|
||||
"Enforce NetBird client configuration through your MDM channel (Intune, Jamf, Kandji, Mosyle, Workspace ONE, JumpCloud, Group Policy). Push management URL, kill switches, and other settings to a fleet of Windows, macOS, and iOS devices.";
|
||||
|
||||
# MDM Integration
|
||||
|
||||
@@ -14,8 +14,8 @@ you and the MDM provider; whatever you can push to that store (manually,
|
||||
via Group Policy, via a Configuration Profile, via your MDM console)
|
||||
becomes effective NetBird policy.
|
||||
|
||||
This page covers Windows and macOS. iOS and Android support is on the
|
||||
roadmap.
|
||||
This page covers Windows, macOS, and iOS (including tvOS). Android
|
||||
support is on the roadmap.
|
||||
|
||||
## At a glance
|
||||
|
||||
@@ -23,11 +23,14 @@ roadmap.
|
||||
| --- | --- | --- |
|
||||
| Windows | `HKLM\Software\Policies\NetBird` (registry) | Group Policy (ADMX) · Intune ADMX ingestion or OMA-URI · `reg import` · MDM-vendor scripts |
|
||||
| macOS | `/Library/Managed Preferences/io.netbird.client.plist` | Configuration Profile (`.mobileconfig`) pushed by your MDM, targeting bundle id `io.netbird.client` |
|
||||
| iOS / tvOS | Managed App Configuration delivered to the app, bundle id `io.netbird.app` (tvOS: `io.netbird.app.tv`) | App configuration payload pushed by your MDM alongside the managed app — see [iOS](#i-os) for the current scope |
|
||||
|
||||
Both backends are the de-facto convention for desktop apps (the same
|
||||
shape Chrome, Edge, Firefox, Zoom, Tailscale, Citrix Workspace, and
|
||||
others use). Any MDM that supports the platform also supports NetBird —
|
||||
there is no NetBird-specific integration to build.
|
||||
Each backend is the de-facto convention for its platform (the registry
|
||||
and managed-preferences shapes are what Chrome, Edge, Firefox, Zoom,
|
||||
Tailscale, and Citrix Workspace use; Managed App Configuration is
|
||||
Apple's standard channel for managed apps). Any MDM that supports the
|
||||
platform also supports NetBird — there is no NetBird-specific
|
||||
integration to build.
|
||||
|
||||
## How enforcement works
|
||||
|
||||
@@ -60,9 +63,12 @@ stale residue on the device.
|
||||
|
||||
## Policy keys reference
|
||||
|
||||
The same 16 keys apply on every platform. Names are camelCase in the
|
||||
managed-configuration payload; the Windows ADMX template renders the
|
||||
PascalCase variant in the Group Policy Editor — both are recognized.
|
||||
The 23 keys below are recognized on every platform. A few of them have
|
||||
no surface on some platforms; those are parsed and ignored there, so a
|
||||
single cross-platform payload is always safe to ship. Names are
|
||||
camelCase in the managed-configuration payload; the Windows ADMX
|
||||
template renders the PascalCase variant in the Group Policy Editor —
|
||||
both are recognized.
|
||||
|
||||
| Key | Type | Description |
|
||||
| --- | --- | --- |
|
||||
@@ -79,9 +85,14 @@ PascalCase variant in the Group Policy Editor — both are recognized.
|
||||
| `disableClientRoutes` | boolean | This peer does not route traffic to other peers. |
|
||||
| `disableServerRoutes` | boolean | This peer is not a router for others. |
|
||||
| `disableMetricsCollection` | boolean | Disable anonymous usage telemetry. |
|
||||
| `enableLocalMetrics` | boolean | Expose the client's local Prometheus `/metrics` endpoint. |
|
||||
| `localMetricsAddress` | string | Listen address of the local `/metrics` endpoint (default `127.0.0.1:9191`). |
|
||||
| `disableUpdateSettings` | boolean | Block every configuration change from UI or CLI on this device (read-only mode). |
|
||||
| `disableProfiles` | boolean | Hide the profile menu in the GUI and reject profile CRUD via CLI. |
|
||||
| `disableNetworks` | boolean | Hide the Networks / Exit Node menus in the GUI and reject the related RPCs. |
|
||||
| `disableAdvancedView` | boolean | Hide the advanced section of the client UI. UI-only: it is not part of the daemon configuration, so nothing is rejected on its account — the client just stops offering the section. |
|
||||
| `allowRemoteJobs` | boolean | Allow management-requested remote jobs (e.g. debug bundles) on this peer. Off by default; equivalent to `--allow-remote-jobs`. |
|
||||
| `debugBundleUploadURL` | string | Override the upload service used for debug bundles produced by remote jobs, taking precedence over the value requested by Management. Must be an `https` URL with a host. |
|
||||
| `splitTunnelMode` | string | `allow` or `disallow` — split-tunnel policy mode (Android only at the client level; harmless on desktop). |
|
||||
| `splitTunnelApps` | string | Comma-separated list of package names that the split-tunnel mode applies to (Android only). |
|
||||
|
||||
@@ -111,7 +122,16 @@ PascalCase variant in the Group Policy Editor — both are recognized.
|
||||
ignored there. Safe to ship in cross-platform payloads.
|
||||
- The `disableMetricsCollection` key is reserved for an upcoming
|
||||
metrics integration; the client recognizes it today but no metrics
|
||||
pipeline is shipped yet.
|
||||
pipeline is shipped yet. It is unrelated to `enableLocalMetrics`,
|
||||
which exposes the client's own Prometheus endpoint.
|
||||
- `disableAdvancedView` is UI-only: unlike the keys above it is not
|
||||
stored in the daemon configuration and never causes a request to be
|
||||
rejected. The daemon reports it to the client, which hides the
|
||||
advanced section. Pushing it as `false` explicitly re-enables the
|
||||
section on a client that hid it for another reason.
|
||||
- `allowRemoteJobs` locks the corresponding client toggle whenever the
|
||||
key is present, including when its value is `false` — so an admin can
|
||||
pin remote jobs off and keep users from turning them on.
|
||||
|
||||
## Windows
|
||||
|
||||
@@ -335,10 +355,101 @@ reboots; on un-enrolled devices the file is wiped at the next reboot
|
||||
(macOS-imposed). Prefer the Custom Mac Application Settings policy
|
||||
above when the fleet is enrolled.
|
||||
|
||||
## iOS
|
||||
|
||||
On iOS and tvOS there is no filesystem location for policy. Apple's
|
||||
channel for a managed app is **Managed App Configuration**: the MDM
|
||||
sends a dictionary together with the managed app, and iOS hands it to
|
||||
that app only. NetBird reads it from the app's own preferences, so the
|
||||
payload must target the NetBird app's bundle id — `io.netbird.app` on
|
||||
iOS and iPadOS, `io.netbird.app.tv` on tvOS.
|
||||
|
||||
The app must be installed **as a managed app** by the same MDM that
|
||||
sends the configuration. A copy the user installed from the App Store
|
||||
themselves cannot receive an app configuration, and NetBird will run
|
||||
with no policy on such a device.
|
||||
|
||||
### Pushing the payload
|
||||
|
||||
The payload is a plain property-list dictionary with the same key names
|
||||
used on desktop:
|
||||
|
||||
```xml
|
||||
<dict>
|
||||
<key>managementURL</key>
|
||||
<string>https://api.netbird.io:443</string>
|
||||
<key>disableProfiles</key>
|
||||
<true/>
|
||||
<key>disableUpdateSettings</key>
|
||||
<true/>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Start from <a href="/docs-static/files/netbird-ios-appconfig.plist" download>netbird-ios-appconfig.plist</a> and delete the keys you do not want to
|
||||
enforce. Where to put it, by provider:
|
||||
|
||||
- **Microsoft Intune**: **Apps → App configuration policies → Add →
|
||||
Managed devices**, platform **iOS/iPadOS**, pick the NetBird app, then
|
||||
**Configuration settings format → Enter XML data** and paste the
|
||||
dictionary.
|
||||
- **Jamf Pro**: **Devices → Mobile Device Apps → NetBird → App
|
||||
Configuration**, paste the dictionary.
|
||||
- **Kandji**, **Mosyle**, **Workspace ONE**, **JumpCloud**: the same
|
||||
field exists on the managed-app assignment, usually labelled *App
|
||||
Configuration* or *Application Configuration*.
|
||||
|
||||
Booleans may be written as `<true/>`/`<false/>` or as `<integer>1</integer>`/`<integer>0</integer>`;
|
||||
both are accepted. Integers and strings behave as on desktop.
|
||||
|
||||
### What each key does on iOS
|
||||
|
||||
<Warning>
|
||||
The policy reaches the NetBird **app**, not the tunnel engine. On iOS
|
||||
the engine runs in a Network Extension, a separate process with its own
|
||||
preferences domain, which Apple's app-configuration channel does not
|
||||
deliver to. So the keys below lock and reshape the interface, and the
|
||||
app refuses configuration changes accordingly — but keys whose effect is
|
||||
applied by the engine on the connection itself (`managementURL`,
|
||||
`preSharedKey`, `rosenpassEnabled`, `rosenpassPermissive`,
|
||||
`blockInbound`, `wireguardPort`, `lazyConnection`) are **not yet
|
||||
enforced on the tunnel**. Treat iOS policy as interface lockdown today,
|
||||
not as connection compliance. Mirroring the dictionary into the shared
|
||||
app group so the extension can read it is tracked work.
|
||||
</Warning>
|
||||
|
||||
| Key | Effect in the iOS / tvOS app |
|
||||
| --- | --- |
|
||||
| `managementURL` | Hides Settings → Connection and the onboarding server step; the profile-creation sheet shows and submits the enforced URL |
|
||||
| `preSharedKey` | The key row reads *Configured* and is locked — no Save, no Remove. The value itself never crosses the bridge |
|
||||
| `rosenpassEnabled` / `rosenpassPermissive` | Locks its own toggle and shows the enforced value |
|
||||
| `disableClientRoutes` | Hides the exit-node selector; the resource list explains why instead of listing |
|
||||
| `disableAutoConnect` | VPN On Demand becomes read-only |
|
||||
| `disableProfiles` | Hides the Profiles section — no create, switch, or remove |
|
||||
| `disableNetworks` | Removes the Resources tab |
|
||||
| `disableAdvancedView` | Hides Advanced (on tvOS, the whole section) |
|
||||
| `disableUpdateSettings` | Read-only mode: nothing is hidden, every configuration control is locked |
|
||||
| `allowRemoteJobs` | Locks the remote debug bundle toggle |
|
||||
|
||||
The remaining keys have no iOS surface and are parsed and ignored:
|
||||
`allowServerSSH`, `disableServerRoutes`, `disableAutostart`,
|
||||
`disableMetricsCollection`, `enableLocalMetrics`, `localMetricsAddress`,
|
||||
`debugBundleUploadURL`, `splitTunnelMode`, `splitTunnelApps`. They are
|
||||
safe to leave in a payload shared with desktop devices.
|
||||
|
||||
### Verifying on a device
|
||||
|
||||
There is no CLI on iOS. A managed setting shows a lock and a **Managed
|
||||
by your organization** note in the app; a gated section disappears
|
||||
altogether. If neither happens, the app did not receive the
|
||||
configuration — check that it is installed as a managed app, that the
|
||||
app-configuration payload is assigned to the same device group, and that
|
||||
the bundle id matches (`io.netbird.app`, or `io.netbird.app.tv` on
|
||||
tvOS).
|
||||
|
||||
## Verifying enforcement
|
||||
|
||||
On any platform, the cleanest verification is the daemon's own debug
|
||||
dump:
|
||||
On Windows and macOS, the cleanest verification is the daemon's own
|
||||
debug dump:
|
||||
|
||||
```bash
|
||||
netbird debug config
|
||||
@@ -373,6 +484,11 @@ Check that the daemon can see the source.
|
||||
`sudo defaults read /Library/Managed\ Preferences/io.netbird.client`
|
||||
— if the file is missing, the MDM payload was not pushed or the
|
||||
bundle id in the profile does not match `io.netbird.client`.
|
||||
- iOS / tvOS: nothing is locked in the app. The app configuration only
|
||||
reaches an app the MDM itself installed, so confirm NetBird is a
|
||||
managed app on that device, that the app-configuration payload is
|
||||
assigned to the same group, and that its bundle id is
|
||||
`io.netbird.app` (`io.netbird.app.tv` on tvOS).
|
||||
|
||||
**The key shows up in the registry / plist but not in `netbird debug
|
||||
config` `mDMManagedFields`.**
|
||||
@@ -393,9 +509,15 @@ The device is not MDM-enrolled. macOS protects
|
||||
controls the directory. Enroll the device with a real MDM provider for
|
||||
persistent rollouts.
|
||||
|
||||
**On iOS, the interface is locked but the connection ignores the policy.**
|
||||
Expected today: the tunnel engine runs in a Network Extension that does
|
||||
not receive the app configuration. See the warning under
|
||||
[iOS](#what-each-key-does-on-i-os).
|
||||
|
||||
**My MDM provider is not in the list above.**
|
||||
Any MDM that can push a Configuration Profile on macOS or write a
|
||||
registry value on Windows works. The mechanism is OS-native, not
|
||||
Any MDM that can push a Configuration Profile on macOS, write a
|
||||
registry value on Windows, or send an app configuration on iOS works.
|
||||
The mechanism is OS-native, not
|
||||
NetBird-specific. If you hit a quirk specific to your provider, please
|
||||
open an issue at
|
||||
https://github.com/netbirdio/netbird/issues with the provider name and
|
||||
|
||||
Reference in New Issue
Block a user