Files
netbird-docs/public/docs-static/files/netbird-macos.mobileconfig
riccardom d09e035d20 docs: sign macOS profiles with CMS, and scope the iOS claims properly
Three review findings, all correct.

`productsign` signs installer packages, not configuration profiles, and
an Apple Developer ID certificate cannot sign a profile at all — Apple's
own guidance is that a `.mobileconfig` is a CMS signed-data message. The
instruction predates this branch but the commit that fixed the malformed
XML comment rewrote it, so it is fixed here rather than carried forward.
It was also misleading in a second way: a profile delivered through an
MDM is signed by the MDM channel, so a managed rollout has nothing to
sign by hand. The step now says that, and gives `security cms -S` for the
case where the profile is handed out some other way.

"Every key is enforced on iOS" contradicted the list of
platform-inapplicable keys three paragraphs below it; it now reads "every
key that applies to the platform", and points at that list.

The engine-applied group — blockInbound, wireguardPort, lazyConnection,
allowRemoteJobs, debugBundleUploadURL — was stated without qualification
under a table headed "iOS / tvOS", while the warning just above says the
tvOS engine never receives the policy. Marked as iOS, with the tvOS case
pointed back at that warning.
2026-09-18 14:37:32 +02:00

205 lines
9.4 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!--
NetBird MDM configuration profile (macOS).
Wraps a `com.apple.ManagedClient.preferences` payload that pushes the
NetBird MDM policy into:
/Library/Managed Preferences/io.netbird.client.plist
Read at runtime by the netbird daemon's macOS loader
(client/mdm/policy_darwin.go — Phase 2). Key names match the canonical
lowerCamelCase form used in docs/netbird.admx and the mdm.Key*
constants in client/mdm/policy.go.
Bundle identifier: io.netbird.client
(confirm against the signed pkg before fleet roll-out)
Distribution:
- delivered through an MDM, the profile is signed by the MDM
channel itself; nothing to sign by hand,
- handed out any other way (Apple Configurator, double-click), it
installs unsigned and asks the user to confirm on recent macOS.
To avoid that, sign it as a CMS message with an identity the
target Macs trust:
security cms -S -N "Your Signing Identity" \
-i netbird-macos.mobileconfig -o signed.mobileconfig
Configuration profiles are not signed with productsign, which
handles installer packages.
- For local dev install: `sudo profiles install -path netbird-macos.mobileconfig`.
- For MDM (Jamf/Kandji/Mosyle/Intune): upload as a Custom Profile.
Editing:
- Replace UUID placeholders below with fresh UUIDs (`uuidgen` on
macOS) when forking this template for a real fleet — each
deployment should have unique UUIDs so the OS treats it as a
distinct profile.
- Tune the PayloadContent values to the policy you want to enforce.
- Remove any key you do NOT want to enforce (the daemon treats an
absent key as "no enforcement" for that field).
iOS note:
This file is macOS-specific. iOS uses managed app config via
UserDefaults[com.apple.configuration.managed] under a different
payload type (com.apple.app.configuration.managed); the wrapper
structure is the same but the inner payload dictionary differs.
See docs/netbird-ios.mobileconfig (Phase 5) when shipped.
-->
<plist version="1.0">
<dict>
<!-- Outer profile envelope -->
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>io.netbird.client.mdm</string>
<key>PayloadUUID</key>
<string>11111111-1111-1111-1111-111111111111</string>
<key>PayloadDisplayName</key>
<string>NetBird MDM Policy</string>
<key>PayloadDescription</key>
<string>Enforces NetBird client configuration. Values written here override any local user / CLI / on-disk setting and are re-applied at every daemon boot and on every 1-minute MDM reload tick.</string>
<key>PayloadOrganization</key>
<string>NetBird</string>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadContent</key>
<array>
<dict>
<!-- Managed preferences payload: writes /Library/Managed Preferences/io.netbird.client.plist -->
<key>PayloadType</key>
<string>com.apple.ManagedClient.preferences</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>io.netbird.client.mdm.preferences</string>
<key>PayloadUUID</key>
<string>22222222-2222-2222-2222-222222222222</string>
<key>PayloadDisplayName</key>
<string>NetBird Managed Preferences</string>
<key>PayloadEnabled</key>
<true/>
<key>PayloadContent</key>
<dict>
<key>io.netbird.client</key>
<dict>
<key>Forced</key>
<array>
<dict>
<key>mcx_preference_settings</key>
<dict>
<!-- ===== Identity / auth (strings) ===== -->
<key>managementURL</key>
<string>https://api.netbird.io:443</string>
<!-- Pre-shared key: secret. Remove the entry entirely
when not used; do NOT leave an empty string. -->
<!--
<key>preSharedKey</key>
<string>REPLACE_ME</string>
-->
<!-- ===== Engine / runtime behavior (bool) =====
Remove any key to leave the field unmanaged. -->
<!--
<key>disableAutoConnect</key>
<false/>
<key>disableAutostart</key>
<false/>
<key>disableClientRoutes</key>
<false/>
<key>disableServerRoutes</key>
<false/>
<key>blockInbound</key>
<false/>
-->
<key>allowServerSSH</key>
<true/>
<!--
<key>rosenpassEnabled</key>
<true/>
<key>rosenpassPermissive</key>
<false/>
-->
<!-- ===== Lazy connections (bool) =====
true forces them on, false forces them off, an
absent key defers to the Management setting.
NB_LAZY_CONN wins over both. -->
<!--
<key>lazyConnection</key>
<true/>
-->
<!-- ===== WireGuard UDP port (int) =====
Range 1-65535. Omit to keep the default. -->
<!--
<key>wireguardPort</key>
<integer>51820</integer>
-->
<!-- ===== Remote jobs =====
allowRemoteJobs is off by default; present at any
value it locks the client toggle, so false pins
remote jobs off. debugBundleUploadURL overrides the
upload service for bundles produced by remote jobs
and must be an https URL with a host. -->
<!--
<key>allowRemoteJobs</key>
<false/>
<key>debugBundleUploadURL</key>
<string>https://uploads.example.com</string>
-->
<!-- ===== Local Prometheus metrics endpoint =====
Unrelated to disableMetricsCollection below, which
governs anonymous usage telemetry. -->
<!--
<key>enableLocalMetrics</key>
<true/>
<key>localMetricsAddress</key>
<string>127.0.0.1:9191</string>
-->
<!-- ===== Split tunnel (Android-only at the daemon level)
Pushed harmlessly on macOS for fleets with mixed
desktop+mobile devices; the macOS daemon ignores it. -->
<!--
<key>splitTunnelMode</key>
<string>allow</string>
<key>splitTunnelApps</key>
<string>com.acme.app1,com.acme.app2</string>
-->
<!-- ===== UI / kill switches (bool) =====
disableAdvancedView is UI-only: it hides the
advanced section and rejects nothing. -->
<!--
<key>disableUpdateSettings</key>
<true/>
<key>disableProfiles</key>
<true/>
<key>disableNetworks</key>
<true/>
<key>disableAdvancedView</key>
<true/>
<key>disableMetricsCollection</key>
<false/>
-->
</dict>
</dict>
</array>
</dict>
</dict>
</dict>
</array>
</dict>
</plist>