* fix(ios): preserve peer identity on re-login, stop creating duplicate peers Every interactive re-authentication registered a brand-new peer on the management server (named after the fallback hostname) instead of re-using the existing one. Root cause was in the netbird-core iOS SDK: NewAuth built a fresh in-memory config that generated a new WireGuard private key, and performLogin() wrote that config (with the new key) back to netbird.cfg on login success — replacing the peer's persisted identity. Regression from the login flow moving into the main-app process (#138), where OAuth switched from the config-reading IPC path to NewAuth. - Bump netbird-core to fix/ios-relogin: NewAuth now loads the existing config (preserving the private key) when a config file is present, only generating a fresh key for first-time login / after logout when no file exists. - Update the stale performLogin() comment that claimed NewAuth does not read the config file. * fix(ios): log when re-login falls back to the default cloud server managementURL(for:) already recovers the server URL from the config file, the logout-surviving server URL file, and the connection cache in turn, so a nil result means no URL is persisted anywhere. Passing "" to NewAuth is harmless for a re-login now that the SDK reads the existing config (its apply() keeps the config URL unless a non-empty one is provided), but a nil URL on an own-server profile that lost every URL source would silently log in against the default cloud. Log that case so it is visible in diagnostics; keep the "" fallback so a genuine first-time login still works. * fix(ios): register peer under device name, not hostname, on interactive login The interactive OAuth login called the SDK's plain login() path, which passes an empty device name; the management server then registers the peer under the machine hostname fallback instead of the user's device name (UIDevice.current.name). Every other iOS registration path (extension Run/LoginForMobile, setup-key login) already passes Device.getName(), so the same device could appear under two different names depending on the entry point. Switch both interactive login call sites to login(withDeviceName:) with Device.getName(): - NetworkExtensionAdapter.performLogin() (main-app OAuth flow) - NetBirdAdapter.loginAsync() iOS branch (was tvOS-only; now unified since both branches pass the device name) Uses the existing LoginWithDeviceName SDK binding — no netbird-core change needed. Affects first-time registration; a re-login reuses the persisted identity. * Update submodule to the release branch * Fix submodule version * Update submodule to the release branch * Update submodule
Start using NetBird at netbird.io
See Documentation
Join our Slack channel
NetBird iOS & tvOS Client
The NetBird iOS/tvOS client allows connections from mobile devices running iOS 14.0+ and Apple TV running tvOS 17.0+ to private resources in the NetBird network.
Install
You can download and install the app from the App Store:
Screenshots
Code structure
The code is divided into 4 parts:
- The main netbird Go code, included as a git submodule at
/netbird-corefrom the NetBird repo, compiled into an xcframework. This contains most of the client logic. - The network extension
/NetbirdNetworkExtensionthat is running in the background where the compiled Go code is executed. - The UI and app code under
/NetBird - The
/NetbirdKit/NetworkExtensionAdapterthat controls the extension and builds the link between UI and extension
Requirements
- iOS 14.0+ / tvOS 17.0+
- Xcode 16.1+
- Go (version determined by the netbird submodule's
go.mod) - gomobile (for iOS builds)
- gomobile-netbird (for tvOS builds — NetBird's fork with tvOS support)
gomobile
For iOS-only builds, install the standard gomobile:
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile-netbird
For tvOS builds, install gomobile-netbird, NetBird's fork of gomobile that adds tvOS support. See: https://github.com/netbirdio/gomobile-tvos-fork
go install github.com/netbirdio/gomobile-tvos-fork/cmd/gomobile-netbird@latest
Run locally
The main netbird Go code is included as a git submodule at netbird-core/.
git clone --recursive https://github.com/netbirdio/ios-client.git
cd ios-client
If you already cloned without --recursive:
git submodule update --init --recursive
Build the XCFramework for iOS:
./build-go-lib.sh
Or for tvOS (includes iOS, iOS Simulator, tvOS, and tvOS Simulator targets):
./build-go-lib.sh --tvos
You can also pass an explicit version:
./build-go-lib.sh 0.2.0
./build-go-lib.sh --tvos 0.2.0
Open the Xcode project, and we are ready to go.
Updating the netbird submodule
To update to a newer netbird version:
cd netbird-core
git fetch --tags
git checkout v0.x.y # or any branch/commit
cd ..
git add netbird-core
git commit -m "update netbird submodule to v0.x.y"
Running on iOS Device
Note: The app cannot run in the iOS simulator. To test the app, a physical device needs to be connected to Xcode via cable and set as the run destination.
Running on Apple TV
Note: The app cannot run in the tvOS simulator. To test the app, a physical device running tvOS 17.0 or later needs to be paired with Xcode.
Firebase Configuration (Optional)
The app supports Firebase for analytics and crash reporting. To enable it, add your GoogleService-Info.plist file to the project root. The app will work without Firebase configuration.
Other project repositories
NetBird project is composed of multiple repositories:
- NetBird: https://github.com/netbirdio/netbird, contains the code for the agents and control plane services.
- Dashboard: https://github.com/netbirdio/dashboard, contains the Administration UI for the management service
- Documentations: https://github.com/netbirdio/docs, contains the documentation from https://netbird.io/docs
- Android Client: https://github.com/netbirdio/android-client
- iOS/tvOS Client: https://github.com/netbirdio/ios-client (this repository)
