Applied the segmentation plan. Added an 'execution log' section with
real IDs, verification results, and a rollback snippet.
Key lesson corrected in the main plan: the original design missed
personal<->personal connectivity (Mac<->iPhone would have broken
when Default was disabled). Added personal-internal policy and a
note that every desired group pair — including a group with itself
— needs an explicit policy, because NetBird defaults to deny when
there is no matching policy.
Explain what Groups are in NetBird, the four places they surface
(policies, setup keys auto_groups, network routes, DNS), and a
concrete segmentation plan for the current mesh:
- servers group: CT100, CT101
- personal group: mbp-13-pro, iphone-15-pro
- Replace default All->All with least-privilege policies
(personal->servers, servers<->servers)
Includes UI and API workflows, a phased migration plan, rollback
strategy, and how to wire auto_groups into setup keys for future
deployments.
Document the operational patterns established while adding CT100 and
CT101 as peers via Docker, plus incidental fixes:
- Docker compose template for headless peer containers
- One-off setup key naming convention and API creation
- Peer rename via API PUT (works, unlike setup keys)
- Mac daemon kickstart via 'sudo launchctl kickstart -k system/netbird'
(service name is 'netbird', not 'io.netbird.client')
- UPNP auto-port-mapping discovery in NetBird client
- CT100 PermitRootLogin drop-in override (first-match-wins sshd quirk)
Document the 'Force relay connection' switch that silently disables
ICE gathering on iOS NetBird (and similar on macOS), which was the
real cause of all peers showing Connection type: Relayed despite
STUN being correctly configured.
Also document bufferbloat diagnosis via macOS networkQuality, which
was a red herring during the P2P investigation (large RTT spikes
were the WiFi/ISP, not NetBird).
Document Setup Keys concept vs SSO, PAT creation and usage, and the
workaround for renaming a setup key — the API silently ignores the
name field on PUT, so the fix is to UPDATE store.db directly and
restart netbird-server.
Document the fix for 'server closed the stream without sending trailers'
gRPC error when exposing NetBird via Nginx Proxy Manager:
- NPM proxy_host advanced_config with grpc_pass for Signal/Management
- Caddy h2c listener enabled via 'protocols h1 h2 h2c'