Magisk NetBird
Minimal Magisk module wrapper for the NetBird CLI daemon. Official NetBird binaries (currently v0.80.0) are bundled for three architectures.
DNS management is disabled by default when joining with netbird.service up.
Download
| Zip | Devices |
|---|---|
magisk-netbird-<version>.zip |
arm64-v8a, armeabi-v7a, and x86_64 |
Latest release: https://github.com/ahsaboy/magisk-netbird/releases/latest
The release ZIP contains all three NetBird binaries and installs on arm64-v8a, 32-bit ARM, and x86_64. Magisk-compatible managers can check for updates from the module's update information. The ACTION button needs Magisk v28+.
Usage
Before reboot:
su -c '/data/adb/netbird/scripts/netbird.service up --setup-key <KEY> --management-url <URL>'
su -c '/data/adb/netbird/scripts/netbird.service status'
After reboot:
su -c 'netbird.service up --setup-key <KEY> --management-url <URL>'
su -c 'netbird.service status'
su -c 'netbird.service log'
To keep the setup key out of shell history and ps output, prefer a file:
su -c 'echo -n <KEY> > /data/adb/netbird/setup.key && chmod 600 /data/adb/netbird/setup.key'
su -c 'netbird.service up --setup-key-file /data/adb/netbird/setup.key --management-url <URL>'
Inspect every peer with connection details (P2P direct vs relayed, latency, traffic, last handshake):
su -c 'netbird.service peers'
In the Magisk app (v28+), or in a KernelSU/APatch manager, the module's
ACTION button runs action.sh without arguments. It prompts for a volume key:
Volume Up starts NetBird and Volume Down stops it. action.sh also accepts an
explicit action for root-shell callers:
su -c '<module-dir>/action.sh status'
su -c '<module-dir>/action.sh refresh'
su -c '<module-dir>/action.sh start'
su -c '<module-dir>/action.sh stop'
su -c '<module-dir>/action.sh restart'
su -c '<module-dir>/action.sh peers'
su -c '<module-dir>/action.sh log'
su -c '<module-dir>/action.sh version'
Supported actions are status, refresh, start, stop, restart, route,
peers, log, version, and help. Use the explicit status action when a
non-interactive status refresh is needed. The log action prints the latest 200 lines
and exits so that an ACTION page does not wait forever; use
su -c 'netbird.service log' for continuous log following. Seeing
daemon: stopped after stop is expected and does not indicate a failed stop. The
same actions can also be invoked directly, for example su -c 'netbird.service peers'.
KernelSU users can open the module's WebUI for a mobile-first control panel.
The page parses status JSON into connection cards and peer rows, and provides separate
views for Peers, Networks/Routes, forwarding rules, health checks, versions, stored
state items, and profiles. Network selection uses
fixed networks select/deselect actions; selecting one route appends to the current
selection. A 0.0.0.0/0 or ::/0 entry is an exit route supplied by the management
service, while the exit peer itself is not selected by this module.
The WebUI does not accept setup keys or arbitrary shell commands. It does not start, stop, or restart the daemon; those lifecycle operations are handled by the module ACTION or boot service. It keeps raw log output out of the interface and focuses on parsed status, peer, route, health, profile, and state information. The top-right language selector supports Chinese and English, follows the system language on first launch, and persists the user's choice. Switching between Peers and Networks changes the view immediately; data refreshes silently with a five-second cooldown to avoid repeated root commands. The manager's ACTION button remains the short, no-argument refresh-and-status entry point.
Configuration
Defaults are set in netbird/settings.sh; override any of them via environment
variables (environment outranks CLI flags in NetBird):
| Variable | Default | Effect |
|---|---|---|
NB_DISABLE_DNS |
true |
Also enforced on up via --disable-dns. |
NB_DISABLE_IPV6 |
false |
When true, up appends --disable-ipv6; this disables NetBird overlay IPv6 and is not a firewall compatibility workaround. |
NB_DISABLE_FIREWALL |
false |
When true, up appends --disable-firewall (client stops managing firewall rules). |
NB_FORCE_USERSPACE_FIREWALL |
auto |
Automatically forced when Android has no usable ip6tables nat table; set explicitly to override detection. |
NB_WG_KERNEL_DISABLED |
auto |
Automatically forced with the userspace-firewall fallback unless explicitly set. |
NB_DISABLE_SSH_CONFIG |
true |
Skips writing /etc/ssh/ssh_config.d (read-only on Android). |
NB_SKIP_NFTABLES_CHECK |
true |
Skips the nftables probe, which always fails on Android. |
NB_SKIP_DNS_PROBE |
true |
Skips the local-resolver startup probe. |
NB_NETWORK_MONITOR |
true |
Upstream defaults to false on Linux; enabled for faster reconnects after network switches. |
NB_STATE_DIR |
/data/adb/netbird |
Writable location for state.json / WireGuard keys (upstream default /var/lib/netbird does not exist on Android). |
NB_LOG_LEVEL |
info |
NetBird log level. |
NB_LOG_MAX_SIZE_MB |
5 |
NetBird's own log-rotation cap for client.log in MiB (upstream default 15). |
NB_WATCHDOG |
on |
Watchdog: auto-restart the daemon when its status stops responding; off disables. |
NB_WATCHDOG_FAILS |
3 |
Failed status probes (one per refresh cycle) before a restart. |
NB_WATCHDOG_MAX_RESTARTS |
10 |
Restart budget; reset after 5 healthy cycles. |
All of the variables above (and any other variable the official client
supports) can be persisted in /data/adb/netbird/.env as KEY=VALUE lines
(# starts a comment); a real environment variable still wins over the file.
Start from the installed template:
cp /data/adb/netbird/netbird.env.example /data/adb/netbird/.env
Daemon-read variables (e.g. NB_LOG_LEVEL) apply after the next
netbird.service restart; no reboot is needed. On Android builds without a usable IPv6
nat table, the module automatically enables NetBird's userspace firewall and userspace
WireGuard so native ip6tables initialization cannot block startup.
Flags added by up persist in config.json and are applied on (re)connect,
so after changing them run netbird.service down followed by
netbird.service up (or netbird.service restart).
The status watcher re-applies both IPv4 and IPv6 Android root underlay rules every refresh cycle
(default 60s), so Wi-Fi/cellular/SIM switches no longer require a manual restart.
The same watcher probes daemon health each cycle and restarts it after 3
consecutive failed probes (watchdog: budget10 restarts, reset after5 healthy
cycles - tunable via NB_WATCHDOG*, disable with NB_WATCHDOG=off).
netbird.service stop (and uninstall) removes all ip rules and iptables rules
the module added.
Dynamic status
While the daemon is running, module.prop is refreshed periodically. Because module descriptions are single-line metadata, status is shown as compact paired fields such as IP/peers, management/signal, relay/interface, memory, CA count, and refresh time. The peers field carries a direct/relay bracket ([P3 R1] = 3 direct, 1 relayed); WD=n shows accumulated watchdog restarts.
Custom CA trust
For self-hosted NetBird servers with a private CA, place PEM certificates in /data/adb/netbird/certs/ as .crt, .pem, or .cer files. /data/adb/netbird/ca.crt is also loaded automatically. Restart NetBird after changing certificates:
su -c 'netbird.service restart'
su -c '/data/adb/netbird/scripts/cert-trust.sh status'
The module injects /system/etc/resolv.conf for the Linux binary runtime. Android's normal app DNS is not changed by this; netbird.service up still disables NetBird DNS management with --disable-dns.
Direct NetBird commands should include the module daemon address:
su -c 'netbird --daemon-addr unix:///data/adb/netbird/run/netbird.sock status'