- Shell 100%
|
|
||
|---|---|---|
| install.sh | ||
| README.md | ||
| uninstall.sh | ||
| update.sh | ||
NetBird EdgeOS
Installs and manages the NetBird WireGuard-based VPN client on Ubiquiti EdgeOS routers. The main challenge on EdgeOS is that firmware upgrades wipe everything outside /config/, so this project stores all state, binaries, and systemd units under /config/ and uses a post-config boot script to restore them automatically after upgrades.
Tech stack
- Language: POSIX shell (
update.sh,uninstall.sh,post-config.d/netbird.sh) and Bash (install.sh) - Target platform: Ubiquiti EdgeOS (Debian-derived, systemd, Vyatta config system)
- External dependencies at runtime:
curl,tar,install,mktemp,systemctl(all present on stock EdgeOS) - No build step, no tests, no package manager
Supported hardware
| Architecture | uname -m |
Example devices |
|---|---|---|
mipsle_softfloat |
mips |
EdgeRouter X, X SFP, Lite |
mips64_hardfloat |
mips64 |
EdgeRouter 4, 6P, 12 |
arm64 |
aarch64 |
EdgeRouter 10X |
Other architectures will cause the scripts to exit with an error.
Prerequisites
- An EdgeOS router with SSH access and root/sudo privileges
- A running NetBird management server (self-hosted) with its URL
- A NetBird setup key for enrolling the router as a peer
- Internet access from the router to:
- GitHub (
github.com,api.github.com) — to download NetBird releases - Your Gitea instance (
git.launcestonit.com.au) — to download these scripts (overridable; see Environment variables) - Your NetBird management server — for ongoing VPN operation
- GitHub (
Installation
Run on the router as root:
curl -fsSL https://git.launcestonit.com.au/LauncestonIT/netbird-edgeos/raw/branch/main/install.sh \
| sudo bash -s -- setup https://netbird.yourdomain.com
Pin a specific NetBird version:
curl -fsSL https://git.launcestonit.com.au/LauncestonIT/netbird-edgeos/raw/branch/main/install.sh \
| sudo bash -s -- setup https://netbird.yourdomain.com 0.71.4
What the install does
- Detects the router architecture and downloads the matching NetBird binary from GitHub Releases
- Installs the binary to
/usr/sbin/netbird - Copies
install.sh,update.sh, anduninstall.shto/config/netbird/for future use - Writes
/config/netbird/mgmt.confwith the management server URL - Creates a bind mount unit (
var-lib-netbird.mount) so NetBird state at/var/lib/netbirdpersists via/config/netbird/state/ - Installs
/config/scripts/post-config.d/netbird.sh— this is what restores NetBird after a firmware upgrade - Starts the NetBird service and enables SSH access over the NetBird tunnel
Enroll the router
After installation, connect the router to your management server:
sudo netbird up \
--setup-key YOUR_SETUP_KEY \
--management-url https://netbird.yourdomain.com \
--allow-server-ssh \
--enable-ssh-root \
--disable-ssh-auth
--disable-ssh-auth skips JWT-to-user mapping and relies on NetBird network ACLs instead, which is appropriate for single-user devices like EdgeRouters.
Updating
After enrollment, use the update script. It reads the management URL from /config/netbird/mgmt.conf automatically.
# Update everything (scripts + NetBird binary)
sudo /config/netbird/update.sh all
# Update scripts only (does not touch the NetBird binary)
sudo /config/netbird/update.sh scripts
# Update NetBird binary only
sudo /config/netbird/update.sh netbird
# Pin a specific version for this run
sudo /config/netbird/update.sh all --version 0.71.4
To permanently pin a version, edit /config/netbird/update.conf:
NETBIRD_VERSION='0.71.4'
Set it to latest (the default) to always track the latest GitHub release.
Re-deploying
Running the install script over an existing installation is safe. It updates the binary and scripts without affecting enrollment state. Existing connections will drop briefly while NetBird restarts.
Uninstalling
sudo /config/netbird/uninstall.sh
Removes the binary, systemd units, boot scripts, cached files, and all configuration/state under /config/netbird/ and /config/data/netbird/. The router's peer record remains in the NetBird management console and must be removed manually.
Environment variables
These override defaults when set in the shell before running the scripts. They are not persisted anywhere — they only affect the current invocation.
| Variable | Default | Used by | Purpose |
|---|---|---|---|
NETBIRD_EDGEOS_BASE_URL |
https://git.launcestonit.com.au/LauncestonIT/netbird-edgeos/raw/branch/main |
install.sh, update.sh |
Base URL for downloading scripts. Override this if you fork the repo or mirror it elsewhere. |
NETBIRD_EDGEOS_DEFAULT_VERSION |
latest |
install.sh, update.sh |
Default NetBird version when none is specified via CLI args or update.conf. |
On-device config files
These are written to the router during install and read by the scripts on subsequent runs:
| File | Format | Purpose |
|---|---|---|
/config/netbird/mgmt.conf |
Shell (MANAGEMENT_URL='...') |
Stores the NetBird management server URL. Sourced by update.sh during script updates. |
/config/netbird/update.conf |
Shell (NETBIRD_VERSION='...') |
Stores the pinned NetBird version. Sourced by update.sh. Created on first install with the default version. |
/config/data/netbird/arch |
Plain text | Cached architecture string (e.g. mipsle_softfloat). Avoids re-detection. |
/config/data/netbird/version |
Plain text | Currently installed NetBird version string. Used to skip no-op updates. |
File layout
Repository (3 files):
install.sh Main installer / refresh script (Bash)
update.sh Update script for scripts and/or binary (POSIX sh)
uninstall.sh Teardown script (POSIX sh)
On the router after install:
/usr/sbin/netbird NetBird binary (wiped on firmware upgrade)
/config/netbird/
install.sh Cached copy of install script
update.sh Cached copy of update script
uninstall.sh Cached copy of uninstall script
mgmt.conf Management server URL
update.conf Pinned NetBird version
state/ NetBird runtime state (bind-mounted to /var/lib/netbird)
systemd/
var-lib-netbird.mount Systemd bind mount unit
netbird.service.d/
mount.conf Ensures state mount before service start
wait-for-networking.conf Waits for vyatta-router.service before starting
/config/data/netbird/
netbird.tar.gz Cached binary archive (survives firmware upgrades)
arch Detected architecture
version Installed version
/config/scripts/post-config.d/netbird.sh Boot script that restores NetBird after firmware upgrade
How it survives firmware upgrades
EdgeOS wipes everything outside /config/ on firmware upgrade. The persistence strategy:
- The NetBird binary archive is cached at
/config/data/netbird/netbird.tar.gz - All systemd unit files and config live under
/config/netbird/ - NetBird state is stored in
/config/netbird/state/, bind-mounted to/var/lib/netbird - The key piece:
/config/scripts/post-config.d/netbird.shruns on every boot. After a firmware upgrade it detects that/usr/sbin/netbirdis gone, re-extracts it from the cached archive, re-installs the systemd units and symlinks, and starts the service. No manual intervention needed.
External services and integrations
| Service | Purpose | Failure impact |
|---|---|---|
GitHub API (api.github.com) |
Resolves latest NetBird release tag |
Cannot install/update when version is set to latest |
GitHub Releases (github.com) |
Downloads NetBird binary archives | Cannot install or update the binary |
Gitea (git.launcestonit.com.au) |
Downloads these management scripts | Cannot install or update scripts; override with NETBIRD_EDGEOS_BASE_URL if migrating |
| NetBird management server | VPN control plane | Peers cannot connect; existing tunnels may survive briefly |
There are no cron jobs, webhooks, or CI pipelines in this repo. Updates are triggered manually by running update.sh on each router.
There is no separate router inventory — the NetBird management console's peer list is the authoritative record of which routers have this installed.
The Gitea instance (git.launcestonit.com.au) is managed by the team. NetBird management console configuration (ACLs, groups, routes) is documented in Zoho Learn under the EdgeOS manual in the "NetBird router" section. Updates to routers are rolled out ad-hoc — there is no fixed schedule.
Development
There is no build or test step. To work on the scripts:
- Clone the repo
- Edit the
.shfiles - Push to the Gitea remote — routers pull updates from the
mainbranch URL whenupdate.sh scriptsorupdate.sh allis run
To test changes without pushing, copy the modified script to a router and run it directly, or override the base URL:
# Serve scripts from a local HTTP server for testing
NETBIRD_EDGEOS_BASE_URL=http://your-dev-machine:8000 sudo bash install.sh setup https://netbird.yourdomain.com
Known issues and gotchas
-
curl | bashdelivery model: The install script is designed to be piped from the Gitea server. If the Gitea instance is down or unreachable from the router, installation and script updates will fail. The NetBird binary itself comes from GitHub, so those are independent failure modes. -
No integrity verification: Downloaded NetBird binaries are not checksum-verified. The scripts trust HTTPS transport security from GitHub. If this matters to you, add checksum verification after the
curldownload step. -
--disable-ssh-authin the enrollment command: This disables NetBird's built-in SSH JWT authentication, meaning anyone who can reach the router over the NetBird network can SSH in as root. Security depends entirely on NetBird ACLs being configured correctly in the management console. -
Every update restarts NetBird and re-enables SSH: Both
install.shandupdate.shcallnetbird downthennetbird upwith SSH flags. This causes a brief connection drop. Even a no-op update (same version) triggers a service restart. -
Significant code duplication:
detect_arch(),resolve_netbird_release(),install_cached_netbird(),ensure_netbird_service(), andenable_netbird_ssh()are duplicated acrossinstall.sh,update.sh, and the embeddedpost-config.d/netbird.shboot script. The boot script is written inline as a heredoc ininstall.sh, so changes must be made ininstall.shand then re-deployed to regenerate it on the router. -
Config files are sourced as shell: Both
mgmt.confandupdate.confare sourced with.inupdate.sh. Malformed content in these files could execute arbitrary commands. Theshell_quotefunction ininstall.shescapes the management URL when writingmgmt.conf. -
install.shis Bash butupdate.shis POSIX sh: The shebang difference is intentional (install uses Bash-only features likelocalin some contexts), but could surprise someone editing them interchangeably. Note:localis actually used in both, but it's widely supported in POSIX-ish shells on EdgeOS (Debian'sdashsupports it as an extension). -
The Gitea URL is baked into the install command: If the Gitea instance moves, every router's cached
install.shstill points to the old URL. You would need to either update the scripts on each router manually or setNETBIRD_EDGEOS_BASE_URLbefore running updates. -
GitHub API rate limiting: The
latestversion lookup hits the unauthenticated GitHub API, which is rate-limited to 60 requests/hour per IP. Unlikely to be a problem unless you're updating many routers from the same NAT IP in quick succession.