Commit Graph
196 Commits
Author SHA1 Message Date
Bruno Mercier Costa 7a0e1e7b60 docs: add troubleshooting for users who already belong to another account (#1042)
* docs: add troubleshooting for users who already belong to another account

Covers the 409 on invite and the 'user account ID mismatch' IdP sync
failure, how to free the user from the other account, and Sign-in
Domains as the way to prevent it. Links the new page from add users,
IdP sync, sign-in domains, account access, the troubleshooting hub and
the sidebar.

* docs: cover same-account 409s and recovery gaps on the user-in-another-account page

A 409 on invite also fires when the user is already in your own
account, for example waiting for approval, so the page now checks
Team -> Users first. Step 2a covers user approval and a domain that the
user's own account already holds, and Confirm it worked routes a
persisting 409 or failed sign-in to Support. Fixes the Identity
Provider Sync click path and drops the duplicate-users note, whose link
target had no such guidance.

* docs: scope account-conflict notes to Cloud and qualify the delete-account re-login note

Address CodeRabbit review: the 409 note on Add users and the IdP sync
rollout note now say they apply to NetBird Cloud, with the self-hosted
embedded IdP case pointing to Team -> Users. The delete-account page no
longer says a new account is always created on the next login: on
Cloud, a domain owned by another account (signup or verified sign-in
domain) joins that account instead.
2026-10-16 09:15:25 +02:00
Maycon SantosandJack Carter cd63a59360 [doc] Document per-target reverse proxy access control (#1014)
* [doc] Document per-target reverse proxy access control

* docs: screenshots, when-to-use and Bypass warning for target access actions

- Add screenshots of the target Access setting and the target-list indicators
- Add "When to use per-target access actions"
- Warn that Bypass authentication makes the path public
- Note that a Block on /admin/ does not cover /admin
- Access logs: describe the User-column icon and tooltip; document access_action=invalid_path

* docs: tighten target access wording

* docs: say where the access log icons appear

---------

Co-authored-by: Jack Carter <128555021+SunsetDrifter@users.noreply.github.com>
2026-10-15 16:07:02 +02:00
cab16a160c Add certificate posture check (#1038)
* add certificate posture checks

* update screenshots

* fix typo

* Correct the certificate posture check docs against the shipped client

* Fix the macOS import command, the Debian environment file, an anchor and a hardware claim in the certificate docs

* Trim the certificate posture docs to what a user needs

* docs: fix certificate posture accuracy and grammar nits

- The 1-hour prompt back-off applies on macOS only (collect_darwin.go)
- Key files are refused as symlinks too, not only certificate files
- Geo and network range checks use the server-observed IP, so "most"
  checks read device-reported data, not "every other"
- State the refresh as 4 hours consistently
- Grammar: "are covered", "Red Hat-based", "in the clear", passphrase phrasing

* docs: tighten certificate posture wording and align overview refresh time

* docs: recommend root-only read access for plain certificate key files

---------

Co-authored-by: Viktor Liu <viktor@netbird.io>
Co-authored-by: Jack Carter <128555021+SunsetDrifter@users.noreply.github.com>
2026-10-15 09:28:58 +02:00
Bruno Mercier Costa 2a748bb210 docs: describe the Waiting for Approval screen for pending users (#1031)
* docs: describe the Waiting for Approval screen for pending users

The dashboard now shows pending users a dedicated Waiting for Approval
screen (dashboard #802) that names the account owner's masked email
(management #7533), replacing the old error page. Update the account
access troubleshooting page to match, and point pending users from the
admin-facing approve-users page to it.

* docs: note the owner address only shows when NetBird can resolve it
2026-10-12 14:15:27 +02:00
9f03f72488 docs: add MDM rollout use case under Use Cases → Deployment (#1029)
* docs: add MDM fleet rollout use case

The MDM reference pages cover installing the client and enforcing its
settings separately, per OS and per vendor, but nothing walks through a
whole rollout. This use case ties install, SSO enrollment, policy, and
update ownership together, with an end-to-end Intune example for Windows
and macOS, and links out to the reference pages for detail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JM8WrDg3kV1PQriXwjmzCb

* docs: move MDM rollout under a Deployment use-case group

Group the MDM rollout guide under a new Deployment section in the Use
Cases sidebar. Reuse existing Intune, desktop app, and Intune compliance
screenshots in the walkthrough. Drop the iOS section and the "What this
does not do" section to keep the guide focused on Windows and macOS
laptops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JM8WrDg3kV1PQriXwjmzCb

* docs: tighten MDM rollout use case for clarity and scan

Polish the fleet rollout page: shorter preamble, clearer policy and update guidance, Related tiles, and a plain checklist without the redundant recap.

* docs: align Intune Ignore app version with update owner

The rollout guide requires Yes when NetBird owns updates and No when Intune does. Document both options on the Intune deploy page so the two guides do not conflict.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brandon Hopkins <brandon@techhut.tv>
2026-10-08 14:47:59 -07:00
Bruno Mercier CostaandClaude Opus 5.5 ad136b2346 docs: Okta SSO setup is self-service in the dashboard (#1027)
The Okta page told readers to email their Client ID, Client Secret and
domains to NetBird support. SSO is now set up in Integrations >
Single Sign-On > Connect Okta, where the wizard takes those values
directly and then asks for domain ownership verification if needed.

- Point the entry path at the Single Sign-On tab and the wizard's
  Get Started / Continue / Connect steps
- Replace the email step with the form fields and the Verify Domain
  Ownership flow (TXT record, Verify Later, email fallback)
- Replace the outdated SCIM-wizard screenshot with one of the
  Enter your Okta details form
- Fix the app.netbird.io link and drop the Okta Verify reference

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:38:24 +02:00
Jack Carterandriccardom 4a9435e701 docs: group MDM policy keys by job and split delivery into per-platform pages (#1020)
* 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.

* docs: iOS enforces every key; document when a change reaches the tunnel

The iOS section was written while the policy stopped at the app: the
network extension that runs the engine has its own preferences domain,
and Apple's app-configuration channel does not deliver there. The app
now mirrors the configuration into the shared App Group and tells the
extension when it changes, so the keys the engine applies to the
connection are enforced too.

What replaces the old warning is a timing caveat, which is what an admin
actually needs in order to plan a rollout. The hand-off happens only
while the app is running: in the foreground a change reaches the tunnel
within about 30 seconds or immediately on activation, but iOS suspends a
backgrounded app, so a policy pushed — or withdrawn — in that window
applies the next time the app is opened. A tunnel brought up by VPN On
Demand or the widget therefore runs on the last policy the app saw.

tvOS keeps the old behaviour and now says so: the hand-off needs a shared
app group, which does not work between the tvOS app and its extension, so
only the interface is enforced there.

Also corrected: blockInbound, wireguardPort and lazyConnection are no
longer listed as having no effect but as having no control to lock, and
debugBundleUploadURL moves out of the ignored list, since the engine
applies it when a remote job produces a bundle. The app-config template
carries the same three keys and the same timing note.

* docs: list allowRemoteJobs among the keys iOS enforces without a control

The key is enforced on iOS like the other engine-applied ones: a peer
whose policy withholds it refuses management-requested jobs. What is not
there yet is the lock on the Troubleshoot toggle, which arrives with the
iOS client PR that introduces that toggle — so promising it in the table
of what the user sees would describe a screen that does not exist.

Moved to the group of keys the engine applies with nothing on screen to
mark, next to blockInbound, wireguardPort, lazyConnection and
debugBundleUploadURL. It moves back to the table once the toggle ships.

* 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.

* docs: group MDM policy keys by job and split delivery into per-platform pages

Rewrite /client/mdm-integration as the concept page and key reference:
a running example (a three-key baseline), the "pinned switches" model
(present means pinned, even as false), and the 23 keys grouped by the
job they do, each with its own anchor and the mistake it invites.

Correct claims that disagree with the client source (v0.80.0):
- disableClientRoutes stops the device using routes (resources, exit
  nodes); it was described as not routing for others
- blockInbound also stops the SSH server and routing; not a kill switch
- since v0.75.0 the app hides managed settings, no "(MDM)" tag
- a policy change restarts the connection
- splitTunnel* have no effect today (Android has no MDM channel yet)
- managementURL pins the server, not the account, on NetBird Cloud
- the pre-shared key is readable by local users on Windows and macOS

Move Windows, macOS and iOS delivery into their own pages under
MDM Deployment, add them to the nav, and point inbound links at the
new per-key anchors.

* docs: fix MDM accuracy points found in review

- integer booleans are ignored on macOS (plist decodes as uint64); say so
- disableAutostart and disableAdvancedView lock nothing; qualify the lock claim
- managementURL: drop the disableProfiles advice, no key pins the account
- drop the unverifiable restart duration and a disableAdvancedView claim
- macOS page: fix 'never write the file' vs the shell-script channel
- Windows page: warn that the sample .reg pins every key
- tighten wording

* docs: say what disableAdvancedView hides (Peers and Resources tabs)

* docs: make clear disableNetworks removes the choice, not the networks

* docs: add recommended MDM policies by device role

* docs: lazyConnection follows the account setting, on by default since v0.74.0

* docs: drop the open-an-issue line from MDM troubleshooting

* docs: make remote jobs optional for every device role

* docs: make disableNetworks and disableAdvancedView optional for laptops

* docs: rename Recap to TL;DR on the MDM pages

* docs: TL;DR on the main MDM page only, drop the lead-in

* docs: list MDM Integration first under MDM Deployment in the nav

* docs: second review pass on the MDM pages

- macOS integer booleans are locked as well as unapplied; say so
- the lock-nothing keys are not desktop-only (disableAdvancedView on iOS)
- drop Linux from disableAutostart (no MDM channel there)
- blockInbound: drop the redundant routed-network clause
- encryption intro: Rosenpass permissive does not need to match
- troubleshooting: check macOS boolean types, no warning is logged
- wording fixes

* docs: correct MDM timing and CLI claims from a macOS lab run (v0.80.0)

- netbird debug config reads the policy file on each call; the daemon
  applies a change at its next reload and logs 'MDM policy changed'
- netbird up --flag on a connected client ignores its flags; the
  rejection examples now say login --flag or up on a disconnected client
- settings-field locks apply immediately; the disableUpdateSettings,
  disableProfiles and disableNetworks gates apply at the next reload
- the restart on a policy change takes a second or two

* docs: MDM results from the Windows and macOS profile labs (v0.80.0)

- netbird logout works under every key and deregisters the peer; with
  managementURL, disableProfiles and disableUpdateSettings pinned, logout
  plus up --setup-key moves a device to another account on the same URL
- a profile-installed macOS policy file is a binary plist, root:wheel 644
- a REG_BINARY (or other unread type) value is not listed as managed
- the policy key inherits Authenticated Users read access

* docs: tighten four MDM statements to what the labs and source show

- no key blocks netbird logout of the active profile (source: only a
  non-active profile logout is gated, by disableProfiles)
- the engine-restart log line appears only while the client is connected
- macOS: binary plist is what a configuration profile produces; the shell
  script writes the same owner and mode
- Windows: the observed fact is that the NetBird key inherits Authenticated
  Users read access, not a statement about the parent key

* docs: address CodeRabbit review on the MDM delivery pages

- iOS: the app must be managed by the MDM, not necessarily installed by
  it (Apple supports taking over a user-installed app); same in the
  iOS app-config template
- macOS: Jamf's Application & Custom Settings takes the bare plist, so
  point Jamf at io.netbird.client.plist (and note the signed .mobileconfig
  upload route); JumpCloud's MDM Custom Configuration Profile takes a
  .mobileconfig per JumpCloud's docs, so drop the bare-plist claim and
  its troubleshooting entry
- Windows: ADMXInstall only ingests the template; values are set through
  Policy/Config/NetBird~Policy~NetBird/<PolicyName>; drop the
  unverified Registry CSP path

* docs: address CodeRabbit's second review of the MDM templates

- netbird-macos.sh: managementURL, allowServerSSH and wireguardPort now
  default to $NULL like every other key; the old defaults pinned them
  (allowServerSSH=true pinned the SSH server allowed) on any run that
  did not edit those lines
- drop the claim that disableMetricsCollection governs anonymous usage
  telemetry from the mobileconfig, the bare plist, the script and the
  ADML help text; the client recognizes the key but nothing reads it

* docs: correct the Mosyle path for the macOS MDM profile

Mosyle takes the .mobileconfig under Management > Management Profiles >
Certificates / Custom Profiles; there is no Custom Settings option with a
preference domain (per Orb and SI Prep deployment guides; Mosyle's own
docs need a login). Drop Mosyle from the bare-plist template header, and
align the mobileconfig header with the Jamf advice on the page.

* docs: drop the profiles-command install tip from the macOS template

macOS 11 and later cannot install configuration profiles with the
profiles command (man profiles, profiles tool 8.0+); point local testing
at a double-click and System Settings > General > Device Management, the
path the lab used.

* docs: make the Windows MDM page Intune-first, with a registry reference section

The page now leads with the Intune workflow: import the NetBird ADMX/ADML
once, create an Imported Administrative templates profile, assign it to a
device group, sync and verify, then the OMA-URI fallback and Intune
troubleshooting. Group Policy, .reg files, JumpCloud and the value-type
table move to a Registry reference section with its own troubleshooting.

New, from Microsoft Learn (Import custom ADMX templates): the current
portal paths, en-us ADML only, and that re-importing an updated template
fails until the profiles and the old template are deleted. netbird.admx
has no namespace dependencies and no combo boxes, so it imports alone.

The Intune install page stays separate; both pages now link to each
other. Main-page links follow the renamed anchors (#value-types,
#intune-troubleshooting).

* docs: move the enforce-settings link to the end of the Intune deploy page

* docs: group the Windows page's Intune steps under one heading

Mirrors the Registry reference section, so the page's table of contents
shows the Intune/registry split. Heading texts and anchors are unchanged.

* docs: rename the first MDM key group to Set the server and startup

The old heading named only managementURL; the group also holds
disableAutoConnect and disableAutostart.

* docs: add a use case to the Lock the client app section

What a developer on a locked Acme laptop sees (app tabs, the two CLI
errors, what still works), plus the finance team's disableNetworks and
Auto Apply exit node variant. Every behaviour is from the macOS and
Windows labs (v0.80.0).

* docs: replace the Lock the client app use case with a plain goals table

Goal, setting, and what users can still do, written for a junior admin.
disableProfiles row says plainly that signing out and into another
account still works (Windows lab W12).

* docs: OMA-URI payloads: <disabled/> pins an on/off setting off

The ADMX's on/off policies write enabledValue 1 and disabledValue 0, so
<enabled/> can only pin a setting on; document <disabled/> for off, the
String data type, and that un-pinning means Not configured (check the
device with reg query, since removing an OMA-URI may not clear it).

* docs: add What you can achieve tables to every MDM key section

Same goal / setting / what-to-know format as Lock the client app, for
server and startup, device exposure, encryption, support and monitoring,
and connection tuning; Lock's table now names values too. Every line
restates a claim already verified in the labs or source.

* docs: reorder the MDM page: goals first, key reference after

- What you can achieve (the six goal tables) comes first, then
  Recommended policies, How the client applies a policy, and the Policy
  keys reference; goal-table keys link down to their reference entries
- reference groups get noun names (Server and startup keys, ...) so no
  two headings share an anchor
- the Acme running example is gone; its three keys become The laptop
  baseline under Recommended policies, which the Windows, macOS and iOS
  pages now link to as their example
- a one-line pin rule opens the goals, since the explanation now follows

* docs: laptop baseline goes to the user-devices group, not just laptops

* docs: rename the laptop baseline to the user device baseline

It applies to every user device (and the iOS page uses it), so the
Recommended policies column becomes User devices, the anchor becomes
#the-user-device-baseline, and the three platform pages follow.

---------

Co-authored-by: riccardom <riccardomanfrin@gmail.com>
2026-10-06 17:41:42 +02:00
Jack Carter 7d1ca1d635 Mention the Enterprise Commercial License wherever a Cloud plan gates a feature (#1023)
* docs: mention the Enterprise Commercial License wherever a Cloud plan gates a feature

Cloud-plan and cloud-only notes now also name the self-hosted Enterprise
Commercial License for IdP sync, EDR/MDM, peer approval and MFA. The Zero
Trust guide, Plans and billing and Self-hosted vs Cloud gain self-hosted
equivalents. SSO notes state that OIDC IdPs work in both self-hosted
editions. The license page's feature table adds peer approval, audit event
streaming and notifications.

* docs: drop the MFA license claim; self-hosted MFA covers local users only

* docs: state that an Enterprise proof of concept includes every licensed feature
2026-10-06 15:53:32 +02:00
Jack Carter 1ea7881248 docs: traffic events streaming fields, delivery, unrecorded traffic, audit events and peer IP allocation (#1010)
* docs: traffic events streaming fields, delivery, unrecorded traffic, audit events and peer IP allocation

* docs: scope traffic event retries to the save and list client-side data loss

* docs: scope traffic event retry guarantee to server-side steps

Reverts a2f549b4's client-side loss list and drops the restart sentence;
the retry and delayed-not-dropped claims now cover only events that have
reached the servers.
2026-10-05 14:34:48 +02:00
Nicolas Frati 8cff42c937 docs: document Agent Network Admin and Usage Viewer roles (#1009)
* docs: document Agent Network Admin and Usage Viewer roles

* docs: unwrap hard-wrapped paragraphs in Agent Network usage pages
2026-10-01 12:06:22 -07:00
Jack Carter dff289cb8b docs: BYOP run command and exposing L4 ports, with a host-networking option (#1008)
* docs: BYOP run command and exposing L4 ports, with a host-networking option

- Bring Your Own Proxy: update the docker run commands to the dashboard
  wizard's current form (NB_PROXY_ADDRESS=:443, named certificate volume);
  the image listens on 8443 by default and runs as uid 1000.
- Bring Your Own Proxy: new section on exposing TCP and UDP services:
  publish and open each listen port, the recreate it takes, a pre-published
  range, or host networking and its port-1024 limit.
- Enable Reverse Proxy: note that changing ports recreates the proxy, and
  document host networking with the two settings it needs.
- Reverse Proxy overview: point BYOP users to the new section.

* docs(reverse-proxy): UFW does not filter Docker-published ports; host mode needs Traefik's ProxyService route
2026-09-30 18:59:24 +02:00
33d1b212fb docs: describe how reverse proxy services share ports (#997)
* docs: describe how reverse proxy services share ports

The reverse proxy page said every L4 service needs a dedicated port and
that each port can only be used by one service. That is not what the
proxy and management do: the conflict check is per cluster, protocol
and port, so a port takes any number of TLS services (told apart by
SNI), at most one TCP service (the catch-all for unmatched
connections), and, counted separately, at most one UDP service.

Also correct the main-port description: a TCP service may listen on the
main port too, and then receives the connections that match no SNI
route, instead of the HTTP reverse proxy.

Verified against checkPortConflict (management/internals/modules/
reverseproxy/service/manager/manager.go) and handleUnmatched
(proxy/internal/tcp/router.go) in v0.79.0, and on a self-hosted
cluster: TLS services on 443 are routed by SNI, unmatched and plain
TCP connections reach the TCP service on 443, a second TCP service on
443 is rejected with 409, and a UDP service on 443 is accepted
alongside them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: TLS listen ports, custom-port fallback and one domain per service

TLS services always need an explicit listen port, including on clusters
without custom port selection, where the dashboard keeps the field
editable; auto-assignment applies to TCP and UDP. On a custom port with
no TCP service, unmatched and HTTP connections are dropped, and non-TLS
connections on the main port take the same fallback as unmatched SNI.
A domain belongs to one service, so the HTTP/TLS same-hostname warning
now says creation fails. In Docker the main port is 8443, so listen port
443 is a custom port. Drop the ECH example from the no-SNI case.

* docs: HTTP hostnames on a custom port fall back to its TCP service

A request for an HTTP service's hostname on a custom port matches no
route there, so it follows the same fallback as any unmatched
connection: the port's TCP service if it has one, otherwise dropped.

* docs: tighten the L4 port overview and the port-sharing warning

The port-sharing warning read as if a second service of any protocol
fails on a port; only TCP and UDP are limited to one per port, while
TLS services share by SNI. Say that directly, shorten the L4 overview
to a summary that links the two sections holding the rules, and name
the listen port in the TCP and UDP mode descriptions.

---------

Co-authored-by: Janek Härtter <janek@netbird.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jack Carter <128555021+SunsetDrifter@users.noreply.github.com>
2026-09-28 16:45:23 +02:00
Jack Carter 82f3d74b54 docs: reverse proxy protocols, path prefix matching, active TCP services (#1007)
* docs: reverse proxy protocols, path prefix matching, active TCP services

Add a protocol support section: WebSocket, SSE and HTTP/2 in HTTP mode,
HTTP/1.1 toward cleartext targets (no h2c), and which mode fits gRPC
with and without TLS. Explain that path prefixes match as text, that the
matched prefix is stripped unless Preserve Full Path is on, and how a
trailing slash matches a whole segment. Add a troubleshooting entry for
an active TCP service whose backend does not answer.

* docs: split path matching from prefix stripping, tighten wording

Move the path-matching notes after the existing overview sentence they
were interrupting, and split them into matching (and the trailing-slash
form) and prefix stripping (and Preserve Full Path). Merge two
overlapping sentences on the upstream HTTP version, and shorten the
troubleshooting cause and solution.

* docs: point the active-TCP troubleshooting entry at the listener check

Step 3 of the checklist is an HTTP request, which cannot confirm a TCP
backend such as SSH or RDP; step 6 checks the listening socket and bind
address on the target host.
2026-09-28 16:44:43 +02:00
Jack Carter 588d11fa25 docs: explain how peers pick and switch routing peers (#1004)
Rewrite the High availability section of How Routing Peers Work around the
routing peer selection order (metric, then direct over relayed, then latency),
the events that make a peer switch, and what a switch does to open
connections.

- Name a direct connection falling back to relayed as a switch trigger when
  routing peers share a metric, and state that different metrics prevent it.
- State that, with masquerade on, every switch resets established TCP
  connections, including the failback to a returning primary, which happens
  as soon as the primary reconnects, before a direct connection is back.
- Replace the 20 ms latency threshold with the 10 ms margin the client uses,
  and state that latency is measured when the connection is set up, so a
  peer keeps its routing peer when latency later changes.
- Add where a switch appears in the client log.
- Production checklist: with equal metrics a peer picks by connection type,
  then latency, when it connects; this is not load balancing.
- Exit nodes: retarget the link to the renamed section.
2026-09-28 16:29:17 +02:00
Jack Carter 557b13130c docs: explain the per-peer lazy connection override and DNS warm-up scope (#1006) 2026-09-28 14:46:40 +02:00
Eduard GertandClaude Opus 5 4df2518616 Add Sign-in Domains page (#970)
* Add Sign-in Domains page

Documents how an email domain is matched to an account: adding a domain,
proving ownership with a DNS TXT record, and what changes for users once it is
verified.

Two points the page is careful about, because both are easy to assume wrongly:

- Verifying a domain decides where *new* users land. It does not move users who
  already have an account of their own, so domains want adding before a team is
  onboarded rather than after.
- A verified sign-in domain is not an SSO domain. Routing a domain to an
  identity provider is a separate step on the integration, which is what lets
  one domain sign in through SSO while another uses Google or a social login.

The four screenshots it references are not in this commit and need to be added
before merge:

  public/docs-static/img/manage/team/sign-in-domains/
    sign-in-domains-settings.png          the Sign-in Domains tab in Settings
    sign-in-domains-pending.png           a newly added domain, Pending
    sign-in-domains-dns-verification.png  the TXT record dialog
    sign-in-domains-login.png             the login page

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Tighten the Sign-in Domains page

Switches the examples to company.com / company.net, drops the step-by-step
walkthrough of how matching works, and trims the instructions down to what a
reader actually needs to do. The prose and the callouts carry the page now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Trim the Sign-in Domains page further

Parallel section titles (Add / Verify / Remove Domain), drops the
"What Changes for Your Users" and "Things Worth Knowing" sections, and cuts
the availability note and the SSO note back to one line each.

The warning now says to add domains before onboarding a team from another
domain, which is the case it actually matters for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Move Sign-in Domains under Settings, and lead with the two domains

Sign-in Domains is a Settings tab in the dashboard, not part of Team, so the
page moves to /manage/settings/sign-in-domains and sits in the Settings nav
after Authentication, mirroring the dashboard's own tab order. Screenshots move
with it to img/manage/settings/sign-in-domains/.

The intro also led with jane@company.com, which would already have matched the
primary domain and so did not show the problem at all. It now establishes
company.com as the account's own domain and company.net as the second one, and
the colleague who needs it is jane@company.net.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Lead with what sign-in domains are for

Retitles the page "Allow Users from Other Domains to Join Your Account", which
is the job it does, and opens with the behaviour rather than with the account's
own domain: users on one business email domain are already joined into one
account, and most businesses have more than one domain -- another location, a
country domain, a second brand -- whose users are not.

Also documents the email route the verification dialog offers for anyone
without DNS access, and matches the dialog's own wording (Verify on the row,
then Start Verification).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Sharpen the intro and drop the primary-domain aside

- The colleague on another domain is not recognized unless invited by hand, so
  the intro says so and links to the invite page.
- "With sign-in domains you prove ownership of those domains, and everyone
  across your organization joins the same account."
- Drops the paragraph about company.com staying the primary domain. Remove
  Domain named that term without defining it afterwards, so it now says "the
  domain your account signed up with" instead.
- Drops the detail about the retry interval widening; that it keeps checking is
  the part a reader needs.
- US spelling, matching the rest of the docs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Shorten the one-account-per-domain note

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Drop the SSO section, and nest the page under Authentication

The "Sign-in Domains and SSO" section read as confusing rather than
clarifying, so it goes along with its recap bullet. The constraint a reader
actually meets survives in Remove Domain: a domain an SSO integration uses
cannot be deleted until it is detached there.

The page also moves under the Authentication group in the sidebar, next to
Peer Session Expiration and Multi-Factor Authentication.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Follow the dashboard: Sign-in Domains lives under Authentication

The dashboard no longer gives sign-in domains a tab of their own, so the
instruction now sends the reader to Settings > Authentication and the section
within it. The screenshot is renamed to authentication-tab.png to match what
it has to show.

Also spells out that joining happens automatically without direct invites,
and drops the same point from the opening paragraph where it was now said
twice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Move the page under Single Sign-On

/manage/team/single-sign-on/sign-in-domains, nested under Single Sign-On in
the Team section rather than sitting under Settings. Screenshots move with it
to img/manage/team/single-sign-on/sign-in-domains/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Put the page at manage/team/sign-in-domains

A sibling of Single Sign-On in the Team section, listed after it, rather than
nested inside it or under Settings. Screenshots follow to
img/manage/team/sign-in-domains/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Fix wording and a stale example domain

The DNS instruction still named www.company.net after the example moved to
company.co.uk, which is the one that actually misleads: that sentence is
telling people where to put the record.

Also a "usees" typo, a link with no object ("unless you invite manually"), a
missing comma after "By default", "as you" where the comparison is to your
domain, "E.g." opening a sentence, and "another one" where it means another
account.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Drop the authentication clause from the recap

It summarised the SSO section, which is gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Add the Sign-in Domains screenshots

- authentication-tab.png: the section under Authentication, with two domains
  pending and two verified, which is what the page describes
- dns-verification.png: the Verify Domain Ownership dialog
- login.png: the login page

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Point domain verification help at NetBird Support

Replace the support@netbird.io mailto links with links to the support
page, and tell users with an account they were not aware of to reach out
so the team can verify their identity and point them to its admin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-28 10:19:37 +02:00
Nicolas Frati b86cb6e8d3 docs: add Reverse Proxy on OpenShift guide (#990)
* docs: add Reverse Proxy on OpenShift guide

Add a guide for running the NetBird reverse proxy on OpenShift with the
rootless UBI image under the restricted-v2 SCC. It covers the proxy
Deployment with self-managed ACME certificates on a PVC, exposure via a
TCP LoadBalancer or TLS-passthrough Routes, wiring a backend through a
routing peer, verification, and troubleshooting.

Adds the page to the Reverse Proxy sidebar and cross-links it from the
overview and Bring Your Own Proxy pages.

* docs: simplify OpenShift proxy guide

Drop the version availability note and the amd64 node restriction since
the rootless UBI proxy image is published for both AMD64 and ARM64, and
replace the interactive token prompt with plain export statements.

* docs: restructure OpenShift proxy guide and add http-01 variation

Make the guide easier to follow for reverse proxy operators:
- Put the LoadBalancer vs passthrough Route decision and the resource
  footprint up front.
- Source the management address from the Secret and drop hardcoded
  namespaces so the manifests apply without edits.
- Add checkpoints after each step and move alternatives (cert-manager,
  replicas, upgrades, removal) into an "Operating the proxy" section.
- Document http-01 with the UBI image's :8081 challenge listener and why
  it requires the LoadBalancer exposure.

Fixes from a test deployment on OpenShift 4.17 with the PR build of the
UBI proxy image:
- Add pkgs.netbird.io (geolocation database) to the egress requirements.
- Show how to switch a pending LoadBalancer Service back to ClusterIP.
- Describe the periodic PROTOCOL_ERROR reconnect symptom of a management
  idle timeout separately from gRPC routing failures.
- Note that autocert handshake warnings during first issuance are expected.
2026-09-28 09:47:01 +02:00
Brandon Hopkins 0d44d0b7ba Trim Okta, Keycloak, JumpCloud, and IIJ ID sync screenshots (#982) 2026-09-24 15:24:55 -07:00
Brandon Hopkins 75080c9e32 Trim Microsoft Entra ID IdP sync screenshots (#981) 2026-09-24 15:19:31 -07:00
Brandon HopkinsandJack Carter cbffc4abea Trim Google Workspace IdP sync screenshots (#980)
* Trim Google Workspace IdP sync screenshots

* docs: render the GCP permissions callout as a Note

* docs: scope the GCP key-creation exception to the NetBird project

Replace the org-wide deletion of iam.disableServiceAccountKeyCreation
with a project-level override, and restore enforcement after the key
is uploaded.

---------

Co-authored-by: Jack Carter <128555021+SunsetDrifter@users.noreply.github.com>
2026-09-24 15:12:04 -07:00
Brandon Hopkins 6641cd73b4 Trim SSO walkthrough screenshots and fix alt text (#983) 2026-09-24 15:11:10 -07:00
Maycon Santos 47b53bdb7d Document the remote-jobs opt-in and MDM keys (#914)
Remote jobs are now an explicit opt-in on the peer (default off), enabled
with --allow-remote-jobs or the allowRemoteJobs MDM policy, and a new
debugBundleUploadURL MDM policy overrides the debug-bundle upload service.
Document both MDM keys in the MDM integration reference, and note the
opt-in requirement plus the new anonymization-level and upload-URL bundle
parameters on the Remote Jobs page.
2026-09-22 16:50:46 +02:00
Bruno Mercier CostaandClaude Opus 5 2c805369e9 docs: fix default.json examples that stop the daemon from starting (#988)
Every `default.json` example on the bootstrap page had at least one value
the client cannot parse, and a bad value there is fatal: the daemon exits
rather than falling back to defaults.

- `ManagementURL` and `AdminURL` were shown as strings. `Config.ManagementURL`
  is a `*url.URL`, so the daemon dies with `cannot unmarshal string into Go
  struct field Config.ManagementURL of type url.URL`. Reproduced on 0.69.0,
  0.73.0, 0.78.2 and 0.79.0-rc.1.
- The Docker example bind-mounted the single file. The client rewrites
  `default.json` on first start via temp-file-plus-rename, and a rename cannot
  replace a bind-mounted file, so the daemon dies with `device or resource
  busy`. This happens with and without `:ro`. Mount the directory instead.
- The Kubernetes example mounted the ConfigMap at the file path with
  `subPath`, which is the same read-only single-file mount. Seed a writable
  `emptyDir` from the ConfigMap with an init container instead.

Verified in a systemd container against the real client: the corrected
`default.json` starts cleanly, keeps the templated values, and regenerates
`PrivateKey`. The fields left untouched (`IFaceBlackList` as an array, the
empty `PrivateKey`, the platform path table, `status --check` values) were
checked and are correct.

The Kubernetes manifest is the one change not run end to end: no cluster was
available. Both failure modes it avoids were reproduced directly with
equivalent mounts, and the pattern it uses is the verified-working one.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 18:24:59 +02:00
Brandon Hopkins 94cc8baa36 Restyle blockquotes and convert callouts to Note (#985)
* Restyle blockquotes and convert callouts to Note

* Fixed SSO prompt grammar
2026-09-17 11:03:22 -07:00
Viktor Liu a2719629fc Document the client local metrics endpoint (#952) 2026-09-16 17:37:26 +02:00
Maycon SantosandClaude Opus 5 ee9e5d9f03 docs: document CAA records for custom domains (#974)
Domains that already have CAA records refuse certificate issuance unless
the certificate authority is authorized, leaving reverse proxy services
unreachable over HTTPS after the domain verifies successfully.

Document the sectigo.com value used by ZeroSSL on NetBird Cloud's managed
proxy clusters, the issue/issuewild records to add, CAA inheritance from
parent domains, and how to check existing records. Add a troubleshooting
entry for certificates that are not issued after verification.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 22:54:39 +02:00
Maycon Santos b046b65d4e [doc] Explain custom domain verification expiry (#969)
* [doc] Explain custom domain verification expiry

Describe the 48-hour verification deadline, hourly cleanup, and activity event
so administrators know why a pending domain disappears and how to register it
again. Include the upgrade window and the exception for legacy service use.

* [doc] Explain custom domain name normalization

Describe how new custom domain registrations normalize case, internationalized
names, and a trailing dot, and reject malformed or wildcard names.
2026-09-11 18:11:29 +02:00
Eduard GertandClaude Fable 5 e246829450 docs: add Control Center Draft Mode guide (#942)
* docs: add Control Center Draft Mode guide

Add a how-to page for the new Draft Mode in Control Center: build a
change on a working copy of the canvas, review the exact API requests,
and deploy everything as one batch. A single running example (giving
DevOps HTTPS access to a not-yet-installed staging server) carries
through entering a draft, the canvas toolbar, node interactions,
placeholder-peer installs, and Review & Deploy.

Along the way:
- Nest Control Center in the sidebar (Overview + Draft Mode) and update
  the overview page: Users view in the intro and quick start, an Edit
  Nodes section covering live edits vs Draft Mode, permissions notes
  including the Network Admin setup-key limitation, and a HashRedirect
  for the renamed #editing-policies-from-the-graph anchor.
- Add a shared <Video> component for screen recordings: lazy playback
  via IntersectionObserver, visible controls, preload="metadata", and
  no autoplay under prefers-reduced-motion.
- Optimize media: re-encode recordings (H.264 CRF 26, 30 fps,
  faststart, audio stripped) and losslessly recompress screenshots,
  cutting the page's media payload from 6.3 MB to 1.2 MB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: image zoom overlay flickering on close

The closing fade-out ran without animation-fill-mode: forwards, so when
the 200ms animation finished the overlay snapped back to full opacity
until React's unmount timeout fired, flashing for a frame or two.
Holding the animation end state covers that gap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: tighten Draft Mode intro

Give the running example its own paragraph and drop the header-chrome
description; the video right below it shows the same thing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: add Focus Mode section and group-from-selection video

Document Focus Mode on the Control Center overview (right-click a node
and choose Focus, or select it and press F) with two screenshots, and
move the F shortcut prose there from the Draft Mode page. Add a
recording of creating a group from a multi-peer selection to the
Draft Mode page. New media compressed like the rest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: correct Focus Mode shortcut order

F is pressed first, then the node is selected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: drop setup-key caveat from Draft Mode permissions note

The Network Admin limitation is already covered where it bites, in the
placeholder install section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: drop Agent Network disambiguation from Add Nodes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: reorder Assign Peers to Groups videos

Show the drag-to-group recording right after the text it illustrates,
then the group-from-selection flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: remove change-type badge list from review section

The review rows do not carry Add/Modify/Delete/Install badges.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: trim group-membership parenthetical from review example

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: react to prefers-reduced-motion changes in Video

The reduced-motion check ran once on mount, so toggling the OS setting
while the page was open either kept videos auto-playing or left them
permanently inert. Listen for MediaQueryList changes: pause and drop
the observer when reduced motion turns on, re-observe when it turns
off.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-04 06:12:55 -07:00
Riccardo Manfrin cb5813d1df Document that a primary nameserver is exclusive on Windows (#950)
* docs: document that a primary nameserver is exclusive on Windows

A peer with a primary nameserver now gets a Name Resolution Policy Table rule
covering every namespace, so all resolution goes through NetBird and nowhere
else. Without it Windows queries every adapter's resolvers in parallel and keeps
whichever answer arrives first, which leaks queries to the local network and lets
another resolver answer for a name NetBird is authoritative for.

Two consequences worth knowing before it surprises someone:

- Zones only the local network resolves stop working while connected, unless
  they are declared as match domains. A more specific rule takes precedence, so
  declaring the zone is the fix. `.local` is exempt, so multicast DNS is
  unaffected.
- Short names depend on which adapter's suffix Windows tries first, and it stops
  at the first "no such name" rather than continuing down the list. On
  domain-joined machines the machine's own domain wins that first attempt, so a
  short name can fail while its fully qualified form resolves.

Placed next to the existing macOS note in the same section, since both are about
what a primary nameserver does beyond catching unmatched queries, and next to the
existing warning about emptying match domains, which the suffix caveat explains
the other half of.

Also documents NB_USE_LEGACY_DNS_RESOLUTION, which restores the old behaviour on
a peer.

* docs: correct how Windows expands short names, and say from which version

Two fixes to the notes added in the previous commit.

The short-name mechanism was described wrongly. Windows does not stop at the
first suffix that misses: it walks the whole suffix list of the preferred
interface, and what it will not do is fall through to another interface's
suffixes. Measured on a Windows 11 machine — with NetBird's adapter preferred, a
list of {fritz.box, netbird.cloud} resolves a name that only exists under the
second entry; with the metric raised so the physical adapter wins, the same name
fails because only that adapter's single suffix is ever tried. The practical
advice changes with it: declaring the local zone with search domains enabled puts
both suffixes in one list, which is what makes short names work either way.

Both notes now say the exclusive behaviour arrives in client v0.78.0 and what
earlier clients did instead, so the page reads correctly for someone still on
0.77, and the environment variable is marked with the version that introduces it.

* docs: say that exclusive resolution is what breaks short names on Windows

The suffix-search behaviour is not Windows' own: without the catch-all NRPT
rule Windows keeps searching the other adapters' suffix lists, and the short
name resolves. Gate the note to v0.78.0 and point at it from the exclusivity
note, so both texts agree on what the change costs.
2026-09-04 11:43:16 +02:00
Bruno Mercier CostaandClaude Opus 4.8 c079d785ce docs: point the domain-classification note to NetBird Support (#958)
On the Add Users page, the indirect-user-invites note told users to email
hello@netbird.io or ping Slack to fix a domain that was not classified as
private. Point it to the NetBird Support page instead, so support requests
go through the same channel as the rest of the docs.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-01 12:00:50 +02:00
Jack Carter ba471cd044 Rebuild the connecting-from-the-office guide on Networks (#956)
* docs: rebuild connecting-from-the-office on Networks

The page walked the legacy Network Routes flow: create a route, assign
distribution groups, and gate the routing-peer policy. Networks is the
current model, and there was no Networks version of this use case
anywhere in the docs.

Rewritten around the Networks building blocks: the posture check hangs
off the access policy whose destination is the office resource, so the
route is not distributed while the device is on site. Adds a limits
section (re-evaluation delay after a network change, ranges carry no
identity, platform coverage) and a summary. Drops the three legacy
route-UI screenshots.

* docs: Android reports local network addresses from 0.77.1

PR #7235 landed the Android side of PeerNetworkRange: the client now
parses local interface addresses from the host app's interface
discovery, so NetworkAddresses is no longer empty. First release
containing it is v0.77.1.

Scopes the known limitation to Android clients older than 0.77.1 and
leads with the fix, mirroring how the iOS 0.69.0 note reads. Also
matches the posture check name in the office guide to the screenshot.

* docs: correct client command, alt text and wording in the office guide

netbird routes is a deprecated alias; the command is netbird networks
list. Alt text now describes what each screenshot actually shows, and
the check name, Wi-Fi spelling and description line are consistent.

* docs: use documentation-only public ranges, scope the Android note in the Zero Trust guide

1.0.0.0/24 and 3.0.0.0/23 are allocated space and a reader can copy
them into a Block check, so the public-block examples now use RFC 5737
documentation ranges.

The Zero Trust guide still stated the Android limitation
unconditionally, which contradicted the posture check reference after
0.77.1.

* docs: tighten the office guide and the Android limitation

Scopes the intro claim to what the page's own screenshots show, stops
overstating what netbird networks list reports, restores the
platform-targeting bullet with Android 0.77.1 included, and leads the
Android section with the version scope so it reads correctly under
Known Limitations.

* docs: do not present macOS interface names as cross-platform

utun100 is the macOS default (client/iface/configurer/name_darwin.go);
wt0 is the default everywhere else. The verify section now names both
once, and the summary talks about the local link and the NetBird
interface instead of en0 and utun100.
2026-08-28 12:17:19 +02:00
Brandon Hopkins 524b810643 Event stream self-hosted note (#955) 2026-08-27 14:31:47 +02:00
Jack Carter 24ca4178e3 docs: selective internal access behind an exit node (#953)
* docs: add selective internal access behind an exit node use case

Documents the two-routing-peer architecture for combining an exit node
with access to specific internal resources only: a resource peer inside
the data center scoped by policies, and an exit node placed on a segment
with internet-only egress. Names the two shortcuts that do not achieve
this (Block LAN access only covers directly attached subnets; host
forward-chain firewall rules are superseded by NetBird's own allow
rules) and adds verification steps, including the netbird down
requirement when enabling Block LAN access over the CLI on a connected
peer. Cross-links from the routing peer concepts and from How Routing
Peers Work.

* docs: make the single-host example clearly outside the subnet resource

* docs: accept all blocked-connection results and scope the exit-node guarantee

* docs: vendor-neutral egress wording and verify bullet polish
2026-08-27 14:22:06 +02:00
Jack Carter c618d99ddc docs: clarify Windows client updates need no user admin on the service path (#944)
* docs: clarify Windows client updates need no user admin on the service path

The 'update needs admin' confusion comes from mixing two paths. Clarify both:

- auto-update: accepting a prompted update is installed by the NetBird
  service (system privileges), not the logged-in user, so no admin rights
  are needed. Only the manual download-link path is a per-machine install
  that requires elevation.
- Windows install: silent install/upgrade needs an elevated (SYSTEM)
  context, which RMM/MDM tools provide; a standard user gets 1625. Add an
  Updating section: the same installer upgrades in place (no separate
  update package), pushed via the same RMM/MDM tool; downgrades are blocked.

All claims lab-verified 2026-08-20 (WS2022, v0.76.0 -> v0.77.0).

* docs: qualify elevation context and warn install-only deploy jobs skip upgrades

- Not every deployment configuration runs as SYSTEM; a user-context job
  fails with 1625. Say the job must run elevated.
- The GPO deployment script exits when NetBird is already installed, so it
  is install-only. Warn that upgrades need an upgrade-capable job.

* docs: correct downgrade behavior per installer and address review on update section

The MSI (WiX MajorUpgrade) blocks downgrades; the NSIS EXE has no version
check and will downgrade. Stop teaching 1603 as a downgrade signature,
add same-installer-type guidance, service-restart warning, rollback path,
Automatic Updates version floors and Latest Version pinning conflict.
Match the page's EXE-first order and <VERSION> placeholder.

* docs: state Force Automatic Updates version scope (server and clients)

* docs: promote update section to top level and fix Automatic Updates note placement
2026-08-25 12:35:54 +02:00
Jack Carter 60e1817611 docs: surface exit nodes under Routes and document broad-access mitigations (#941)
Exit nodes previously lived only under Use Cases. Add them to the Routes
sidebar group and mention them on the Routes overview. Document that a
default route grants access to everything the routing peer can reach,
with Block LAN access and network isolation as mitigations, and link
How Routing Peers Work back to the exit nodes guide.
2026-08-25 11:20:35 +02:00
Jack Carter 62baad95a1 docs: standardize on "NetBird client" over "agent" for the client software (#940)
* docs: standardize on "NetBird client" over "agent" for the client software

* docs: address review feedback

- fix "a software" grammar and use lowercase "NetBird client"
- define routing peer as a peer whose client bridges, keeping peer and client distinct
- correct kernel-space claim: the kernel WireGuard data path is what runs in the kernel
- clarify which address the application uses to reach the SOCKS5 proxy from a separate container
2026-08-21 13:24:33 +02:00
Brandon Hopkins d810fdc457 Improve CrowdSec hardening and reverse proxy troubleshooting (#917)
* Improve CrowdSec setup, recovery, monitoring, and access-log documentation

* Refine CrowdSec dashboard recovery and access-log field documentation

* Image and API ref update

* Api ref fix

* Probe both api/.env
2026-08-19 10:58:01 -07:00
Brandon Hopkins b1629b1d11 Settings docs accuracy audit: gap fixes and three new pages (#936)
* Enforce periodic user authentication

* Multi-Factor Authentication

* IPv6 minor fixes

* Delete account clarification

* Notifications, perms, and billing

* Update metrics, auto-update, lazy connections

* Settings docs audit fixes plus two new pages

* Update self-hosted notications

* rework client page and navigation

* Matching naming to product

* Coberabbit suggested fixes

* Peer Session Expiration title

* Remove dash
2026-08-19 08:07:46 -07:00
Misha Bragin 3f08eafb7b docs: explain how to update billing info and payment method (#934)
Add a "Updating Billing Information and Payment Method" section to the
  Plans & Billing page covering the path from Settings > Plans & Billing >
  Manage Plan into the Stripe billing portal, where users can change their
  payment method and use "Update information" to edit company name, billing
  address, billing email, and tax information.

  Note that this is NetBird Cloud specific functionality — self-hosted
  deployments are not billed through the Stripe billing portal.
2026-08-18 19:59:05 +02:00
Jack Carter 0f8d90e0ee docs: fix self-hosted SCIM Tenant URL and explain duplicate users (embedded Entra SCIM) (#925)
* docs: fix self-hosted SCIM Tenant URL and explain duplicate users

The embedded Entra SCIM page showed the NetBird Cloud Tenant URL
(api.netbird.io) on a self-hosted page; a reader who copies it points
Entra at Cloud and provisioning silently fails. Use the reader's own
management domain instead.

Add a section explaining why externalId must map to objectId: NetBird
matches users by stable ID, not email, so a mailNickname externalId
creates a same-email duplicate of an existing sign-in user. Includes
remediation for accounts that already have duplicates.

* docs: safer duplicate-user remediation via integration reset

Address review feedback: don't tell operators a SCIM-created account is safe
to delete based on origin alone. Recommend deleting the integration to clear
the synced accounts (sign-in accounts are untouched), then reconfiguring with
externalId=objectId and re-provisioning. If removing a single account, verify
ownership and migrate peers/access first.
2026-08-18 12:22:39 +02:00
Brandon Hopkins dfe4a283f2 Codespell flagged fix (#932) 2026-08-18 03:18:40 -07:00
Brandon Hopkins 7f964a344f Update posture checks video and navigation (#926)
* Update video and fix nav

* Quick edits (Coderabbits Findings)

* Releases to docs audit

* peer network range mobile fix
2026-08-18 02:05:33 -07:00
Brandon Hopkins 627d18fda0 Document the Permissions settings tab (#931)
* Add new permissions page and fix zero trust doc

* Remove API mention
2026-08-17 10:23:14 -07:00
Bethuel Mmbaga f5dacdd2fb Add IIJ ID SSO and SCIM provisioning guides (#922) 2026-08-14 19:21:58 +03:00
Jack Carter 204c2793f3 docs: unmanaged DNS mode also ignores Custom Zone records (#916)
* docs: unmanaged DNS mode also ignores Custom Zone records

A peer whose group is under DNS Settings -> Disable DNS Management (or
started with --disable-dns) never gets NetBird's resolver wired into the
OS, so Custom Zone records silently stop resolving along with
nameservers. The unmanaged-mode description, the Custom Zones
limitations list, and the DNS troubleshooting flow now say so, and the
troubleshooting page gains a confirm-managed-mode first check (the
existing --disable-dns isolation test reproduces this exact cause and
misreads as 'not NetBird DNS').

Also fixes the API Reference links to the canonical /api path (/ipa
redirects).

* docs: fix DNS API Reference link on the DNS landing page
2026-08-11 17:24:23 +02:00
Jack Carter 2cbebc3323 docs: explain macOS DNS resolver behavior for match-only vs primary nameservers (#912)
* docs: explain macOS two-resolver-stack DNS behavior and the match-only vs primary nameserver split

Lab-validated against client 0.76.3 (macOS 26, NetBird Cloud):

- DNS troubleshooting: new Issue 5 'dig and host fail, but browsers and
  curl work (macOS)' with the scoped-resolver vs resolv.conf explanation,
  the language-runtime split table (pure-Go/dnspython/c-ares vs
  getaddrinfo), and the Windows nslookup-vs-NRPT analog; renumbered
  Issues 5-8 to 6-9; checklist step 6 now says why it prescribes
  dscacheutil/Resolve-DnsName
- Internal DNS Servers: primary-vs-match now explains that match-only
  leaves resolv.conf untouched on macOS; new warning that emptying a
  match group's domains silently drops the search suffix (masked on
  domain-joined Windows); split-horizon example gains the
  route-everything-internal variant (the OpenVPN migration shape)
- DNS overview: macOS line now distinguishes scoped resolvers from the
  primary case, where configd regenerates resolv.conf with NetBird's
  resolver

* docs: add dashboard screenshot for the route-all-internal nameserver example

* docs: polish wording in the macOS DNS additions

* docs: promote the route-all-internal example to its own section

* docs: drop the Example prefix from the nameserver scenario headings

* docs: state the public-resolution prerequisite for an internal primary nameserver

* docs: make the direct-resolver check precise

* docs: anchor the scoped-resolver term to scutil output and split the dense solution paragraph
2026-08-11 16:47:56 +02:00
Bethuel Mmbaga fd04046f5f Update Entra ID SCIM docs for the new Azure portal UI (#909) 2026-08-10 12:25:39 +03:00
Jack Carter f403129f66 Navigation cleanup: MDM deployment under Peers, purge stale tutorials, MSP portal refresh (#906)
* docs: move MDM deployment guides under Manage > Peers

The five fleet-deployment guides (GPO, macOS .pkg, Jamf Pro, Kandji,
Intune) lived under Integrations, but nothing in them integrates with
NetBird's platform — they are peer onboarding at scale, which lives
under Peers. The label also collided with Access Control's
'Integrate MDM & EDR', which uses MDM in the opposite sense.

- Move pages from /manage/integrations/mdm-deployment/ to
  /manage/peers/mdm-deployment/ with a permanent wildcard redirect
- Re-point legacy /how-to redirects directly at the new paths
- Move the nav group under Peers as 'MDM Deployment'; remove the
  now-empty Integrations group
- Update internal links

* docs: link full GPO deployment guide from MDM integration page

* docs: show setup-key secret wiring and replica naming for k8s routing peers

Fold the two verified-novel bits from the Access Infrastructure
autoscaling tutorial before purging it:

- Replace the 'use a secret' Note with the actual kubectl create
  secret + secretKeyRef wiring (matches what the NetBird operator
  injects for routing peers)
- In the HA section, note that removing the static NB_HOSTNAME lets
  each replica register under its pod name (client falls back to
  os.Hostname(), which is the pod name in Kubernetes)

* docs: purge redundant Access Infrastructure tutorials

The four pages under Manage > Peers > Access Infrastructure were
2024-era SEO tutorials that duplicated canonical feature docs and
carried outdated claims (pre-rewrite SSH model without the built-in
SSH server, a Docker section that never actually enrolls the
container with a setup key, CrowdStrike presented as the only EDR
integration, stale v0.29 output and vintage-UI screenshots).

Cross-checked each page against its canonical counterpart; nothing
novel remained (the two useful Kubernetes snippets were folded into
the routing-peers use case in the previous commit).

- Delete the four pages and their screenshot directory
- Remove the Access Infrastructure nav group
- Redirect each URL to its canonical replacement:
  secure-remote-webserver-access -> /manage/peers/ssh
  setup-keys-add-servers-to-network -> /manage/peers/register-machines-using-setup-keys
  access-internal-resources-from-autoscaled-environments -> /use-cases/kubernetes
  peer-approval-for-remote-worker-access -> /manage/peers/approve-peers
- Re-point the legacy /how-to redirects at the same targets to avoid
  redirect chains

* docs: reorder Peers nav into enrollment, approval, day-2 flow

Group the five enrollment methods first (Add Peers, Setup Keys,
Bootstrap via Config File, MDM Deployment, Browser Client), then the
Approve Peers admission gate, then running-peer features (SSH, Lazy
Connections, Remote Jobs) and Auto Update last. Approve Peers
previously sat between two enrollment pages.

* docs: cross-link DNS aliases and internal DNS pages, fix tutorial inaccuracies

The two pages solve adjacent problems (NetBird-hosted records vs
forwarding to existing internal DNS) but never pointed at each other.
Add a which-page-do-I-need Note to each.

Also fix defects in the DNS Aliases tutorial found while cross-checking
it against the Custom Zones reference and dashboard source:

- 'Keep this enabled' implied search domain is on by default; it is
  off by default (DNSZoneModal.tsx: enable_search_domain ?? false)
- Step 3 said 'wildcard resource' but the steps add exact-name domain
  resources
- Wrong alt text ('Delete DNS Zone') on the zone-config screenshot
- Add missing meta description and a link to the Custom Zones
  reference

* docs: align MSP portal page with 2026 partner program, rename For Partners nav

Cross-checked the MSP portal page against the 2026 MSP/MSSP Partner
Program document:

- Point the application link at netbird.io/use-cases/msp (the program's
  canonical page) instead of a demo-form URL displayed as netbird.io/msp
- State tenant plan options (Team or Business) and the post-trial
  minimum (Team plan with one user)
- Mention CSV/PDF usage export alongside the API
- Clarify the 3-day trial for existing accounts brought in as tenants:
  it is a window to subscribe the tenant under the MSP account
- Add a subtle msp@netbird.io contact line at the bottom

Also rename the For Partners nav entries by deliverable instead of
audience (the section header already says who it's for): MSP Portal,
Distributor Portal, Deploy with Acronis.

* docs: update CLAUDE.md for agent-network, proxy.js, and tooling gaps

Audited every claim against the current repo. Stack, routing, security,
and convention claims all still hold; four gaps had accumulated:

- Add agent-network/ to the content structure list
- Document src/proxy.js in URL Routing: /api data requests must be
  rewritten there because the config rewrite loses data-request context
  on client-side navigation (Next.js #39669) and strips pageProps
- Add npm run lint:mdx; note npm run gen requires a Go toolchain
- Note fenced mermaid code blocks render as diagrams

* docs: address review findings on PR #906

- Move the MDM deployment screenshot directories to match the new page
  paths; the URL rewrite had updated MDX image references without
  moving the assets, breaking all Intune/Jamf/Kandji images
- Normalize pre-existing double slashes in Jamf and Kandji image URLs
- Align the routing-peers secret example with bootstrap-via-config-file
  (same secret name, so both now use the NB_SETUP_KEY data key)
- DNS aliases: include the routing peer's group in the zone's
  distribution groups. Verified in client source: the DNS route
  interceptor (priority 100) outranks local zone records (priority 75)
  and never falls through, so clients forward routed-domain queries to
  the routing peer, which must receive the zone to answer
2026-08-07 14:37:41 +02:00
Bruno Mercier CostaandClaude Opus 4.8 fe16bcbfed List each supported IdP as a heading on the idp-sync page (#899)
The supported identity providers were a bullet list of links, so none of
them appeared in the "On this page" navigation. Make each one a
subsection heading with its setup link, and promote Generic SCIM to a
top-level section so it is a peer rather than a sub-item. Also fix a
typo (identify -> identity).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 11:19:46 +02:00
Jack Carter 3f02e402da docs: masquerade-off HA is achievable, not impossible (#893)
* docs: masquerade-off HA is achievable, not impossible

Both the routing-peers page and the masquerade page stated that high
availability "stops working" with masquerade off. That reads as a flat
impossibility and loses a legitimate use case (source IP preservation for
audit, per-user database rules, or firewall policy keyed on the real source).

What is actually true is narrower: NetBird's half of the failover still
works, clients move to the standby peer on their own. What is missing is the
return route inside the destination network following that move. State the
condition instead of the impossibility, and add a short section on what
meeting it takes: distinct metrics so the active peer is the same for every
client, plus a virtual IP or a router-moved route so the next hop follows.
Both live outside NetBird, so the section names the pattern rather than
shipping a third-party config we would then own.

Also:

- Soften "failover is automatic and immediate". Clients re-select within
  seconds, which is fast but not instant, and "immediate" invites a support
  ticket from anyone who measures it. Phrased so it does not assert whether
  the client or the management side detects the loss, which this change did
  not verify.
- Warn against pointing the return route at both peers, as two static routes
  or an equal-cost pair. It is the intuitive fix and it fails silently.
- Note that the second interruption on recovery cannot be avoided by pinning
  the virtual IP to the standby, since the client's switch back is automatic.
  Pinning the route while the client moves back strands the return path.
- The return route can live on the destination subnet's default gateway even
  when the gateway and the routing peer share that subnet, which is the only
  option when the destination host is not the customer's to configure. The
  page previously offered the gateway only for a different-subnet
  destination, and its persistent-config steps assume host access throughout.

* docs: health check must cross the path, not test the peer

A routing peer can stay enrolled and report healthy, with its WireGuard
interface present, while being unable to forward from the tunnel to the
destination subnet: a failed LAN interface, or a firewall change. Nothing
fails over in that state. NetBird sees a reachable peer, and a health check
that only looks for the interface sees a healthy one, so the return route
stays pointed at a peer that forwards nothing until someone intervenes.

Say that the check has to reach a destination through the tunnel.

* docs: held connections stall across a failover, they do not reset

Measured on a routing-peer pair with masquerade off: a held TCP connection
survives the switch. Four failovers, graceful shutdown and hard kill, all
showed the same signature — one round trip with multi-second latency, then the
same connection continuing with monotonic sequence numbers. No resets, and no
RST on the wire in any of them.

The reason is a property of masquerade being off: the addresses on the
connection do not change when another peer takes over, so the flow is portable
between peers, and the routed ACL accepts on addresses rather than on
connection state, so the standby forwards mid-stream packets it never saw a
handshake for.

Note this is specific to masquerade being off. The general high-availability
section still says established connections reset, which is the masquerade-on
default, where the standby would translate to a different source address.

Also trims the mechanism guidance to name the pattern rather than lean on any
one implementation, since which mechanism is right may change.

* docs: scope the reset claim to masquerade on, fix leftover contradiction

Review of the branch turned up three problems.

The Networks overview still said disabling masquerade 'breaks high
availability', one click from the page arguing it does not. Reworded to say it
makes high availability something you arrange rather than something you get.

Neither reset/stall sentence named its masquerade scope, so a reader with
masquerade off met both and they flatly disagreed. The general failover section
now scopes its reset claim to masquerade on, names the reason (the standby
translates to a different source address), and links onward.

'Stalls for the length of the failover' understated it. Measured stalls were 6
to 13 seconds against a 6 second failover, because the sender waits for its
next retransmit after the path returns. Says so, with the range, and keeps the
claim hedged to what was observed rather than asserting connections are never
broken.
2026-08-03 09:52:02 +02:00