Commit Graph

2866 Commits

Author SHA1 Message Date
Zoltán Papp
dd9c15072f [ci] Skip client/ui-wails in go test runs
main.go embeds frontend/dist with //go:embed, so any go-list-based test
sweep that touches the package fails at compile time before pnpm build
has populated the directory. The release pipeline runs the frontend
build via the goreleaser before-hook; the test workflows do not, and
should not, ship a Node toolchain just to compile a UI binary that has
no Go-side unit tests anyway.

Add a /client/ui-wails exclude to the test go-list filter on Linux,
Darwin and Windows.
2026-05-05 12:56:59 +02:00
Zoltán Papp
4c743bc03d Merge remote-tracking branch 'origin/main' into ui-refactor
# Conflicts:
#	client/internal/peer/status.go
#	client/proto/daemon.pb.go
#	client/proto/daemon_grpc.pb.go
#	go.mod
2026-05-05 12:49:09 +02:00
Zoltán Papp
2e61b42e92 [client/ui-wails] Slim the tray menu, move toggles to Settings page
The Fyne 1:1 tray pulled the entire daemon-config knobset (Allow SSH,
Connect on Startup, Quantum-Resistance, Lazy Connections, Block Inbound,
Notifications) into a Settings submenu — useful in a tray-only UI but
redundant now that the Wails app has a real Settings page. Drop the
submenu and route a single top-level "Settings" entry to /settings;
"Create Debug Bundle" stays at the top level for support workflows.

Side effects:
  - flipFlag and ptrBool go away with the checkbox callbacks.
  - loadConfig keeps seeding notificationsEnabled (the tray still gates
    OS toasts in onSystemEvent on it) but no longer mirrors any other
    config field.
  - Unused menu/notify constants (Allow SSH, Connect on Startup, ...,
    notifyErrorSettingsFmt) are removed from the central const block.
2026-05-05 12:19:41 +02:00
Zoltán Papp
3f8de2a149 [client/ui-wails] Hide Dock entry on macOS via LSUIElement
The legacy Fyne client and the sign-pipelines-built .pkg both run NetBird
in macOS Accessory mode (LSUIElement=1) — tray-only, no Dock entry, no
Cmd-Tab presence. The Wails build's bundled Info.plist (used by `task
darwin:package` for local development) didn't carry the flag, so the
.app bundle a developer builds locally diverged from the signed release.

Add LSUIElement to both Info.plist and Info.dev.plist so the local dev
flow matches what users see.
2026-05-05 12:03:09 +02:00
Zoltán Papp
bc609c3ae7 [client/ui-wails] Wire up enforced-update tray menu item
Surface the Fyne UI's "Download latest version" / "Install version X.Y.Z"
About-submenu entry in the Wails tray. The item starts hidden and is
revealed by onUpdateAvailable when the daemon emits EventUpdateAvailable;
opt-in updates open github.com/netbirdio/netbird/releases/latest in the
browser, enforced updates surface the in-window /update progress page
and call TriggerUpdate on the daemon.

Also lift every user-facing string and external URL in tray.go into
named const declarations at the top of the file, so future copy edits
and (eventual) localisation have a single source of truth.

The /update React route is the frontend counterpart and is owned by the
React side of the refactor.
2026-05-05 11:56:57 +02:00
Pascal Fischer
97db824929 [management] fix proxy reconnect (#6063) 2026-05-04 20:43:25 +02:00
Viktor Liu
77a0992dc2 [misc] Disable govet inline analyzer and tidy go.mod (#6066) 2026-05-05 02:59:41 +09:00
JungwooShin
104990dfdd [client] Display QR code for device auth login URL (#5415) 2026-05-04 18:59:29 +02:00
alexsavio
bde632c3b2 [client] Replace WG interface monitor polling with netlink subscription on Linux (#5857) 2026-05-04 18:49:39 +02:00
Lauri Tirkkonen
4268a5cfb7 [client] Use atomic write/rename pattern for ssh config 2026-05-04 18:24:52 +02:00
Zoltán Papp
e3994d0c99 [client] Drop Mesa3D opengl32.dll, bootstrap WebView2 in Windows installers
Wails3 uses the WebKit-style WebView2 runtime instead of Fyne's OpenGL
backend, so the Mesa3D opengl32.dll payload that the Fyne build needed
for RDP/VM rendering can leave the .exe and .msi installers. Add a
WebView2 bootstrap step that probes the EdgeUpdate registry markers
(both HKLM\WOW6432Node and HKCU) and silently runs
MicrosoftEdgeWebview2Setup.exe only if the runtime is missing.

NSIS uses an inline macro adapted from Wails3's wails_tools.nsh; WiX
uses a deferred CustomAction gated on RegistrySearch properties. Both
expect the bootstrapper payload at client/MicrosoftEdgeWebview2Setup.exe,
which the sign-pipelines build step generates with `wails3 generate
webview2bootstrapper`. The matching sign-pipelines change lives in
that repo's PR.

The uninstall section keeps an unconditional `Delete opengl32.dll` so
upgrades from older Fyne builds clean up the leftover file.
2026-05-04 17:36:30 +02:00
Zoltán Papp
ba6e10cef3 [client/ui-wails] Pad macOS tray PNGs for proper menubar sizing
Wails3's macOS systray sets the NSImage size to the status bar thickness
(~22pt) on a square frame. The legacy Fyne PNGs had almost no horizontal
margin (the logo filled all 256x256), so under that explicit resize the
glyph stretched to the full menubar height — noticeably larger than
neighbouring SF Symbols-style indicators.

Pad each *-macos.png from 256x256 to 366x366 with transparent gravity:center
extent, leaving the glyph at ~70% of the rendered size. Same source PNGs,
no resampling, just more breathing room around the alpha-only template.
2026-05-04 17:12:12 +02:00
Zoltán Papp
ce53981b55 [client/ui-wails] Fix Windows manifest version format
Win32 assembly manifests require a four-part version (MAJOR.MINOR.BUILD.REVISION
per the Microsoft schema). The Wails template shipped a three-part "0.0.1",
which Windows rejects with "Activation context generation failed (...) The
value 0.0.1 of attribute version in element assemblyIdentity is invalid",
so the .exe never reaches main(). Pad to "0.0.1.0".
2026-05-04 16:20:15 +02:00
Zoltán Papp
a69037630b [client/ui-wails] Skip tray click-to-toggle on Linux
GNOME Shell + AppIndicator extension opens the attached menu on
left-click in addition to firing SNI Activate, so binding the window
toggle to the click handler made both the window and the menu pop on a
single click. The default Wails3 SystemTray.applySmartDefaults made it
worse: AttachWindow alone is enough to install ToggleWindow as the
implicit click handler, so dropping OnClick wasn't sufficient.

Mirror the legacy Fyne client: skip both AttachWindow and OnClick on
Linux and expose the main window through an explicit "Open NetBird"
menu item. Windows and macOS keep the click-to-toggle behaviour where
the OS cleanly separates left and right click.
2026-05-04 16:08:10 +02:00
Zoltán Papp
df58935cc0 [client/ui-wails] Set NetBird window and app icon on Linux
Wails3 falls back to its bundled bird logo when no Icon is supplied via
application.Options or LinuxWindow. Embed the 256x256 NetBird PNG and
wire it through both fields, plus set ProgramName=netbird so GTK's
g_set_prgname picks up the icon from the installed .desktop file. Tested
on Fedora 40 + KDE Plasma; the titlebar and taskbar now show the NetBird
logo.
2026-05-04 14:34:45 +02:00
Zoltán Papp
a1743dbf9b [client/ui-wails] Fix Fedora ayatana-appindicator package name
The RPM dependency name on Fedora is libayatana-appindicator-gtk3 (not
libayatana-appindicator3 — that's the Debian/Ubuntu spelling). Verified
with dnf install on Fedora 40.
2026-05-04 14:00:52 +02:00
Zoltán Papp
f9771de3f5 [client/ui-wails] Switch release pipelines from Fyne to Wails UI
Repoint goreleaser configs and the release workflow at client/ui-wails so
the published Linux deb/rpm, Windows binaries and macOS UI binaries are
built from the Wails source. Linux nfpm deps swap libappindicator/Fyne
GL stack for libgtk-3, libwebkit2gtk-4.1 and libayatana-appindicator3,
and the packaged .desktop file launches the binary with
WEBKIT_DISABLE_DMABUF_RENDERER=1 so RDP/VM sessions render correctly.
Frontend bindings are now committed; the release jobs add Node 20 and
pnpm 9 and run the frontend build via the goreleaser before-hook.
2026-05-04 13:00:13 +02:00
Zoltan Papp
a547fc74ed [client] Use ctx.Err() instead of gRPC codes.Canceled to detect shutdown (#6019)
Detecting shutdown by inspecting the gRPC status code conflates a local
context cancellation with a server- or proxy-sent codes.Canceled. When
the latter occurs (e.g. an intermediary proxy resets the stream), the
retry loop silently terminates and the client never reconnects.

Switch to ctx.Err() in the signal Receive loop and management Sync/Job
handlers, and stop matching gRPC Canceled/DeadlineExceeded in the flow
client's isContextDone helper. With this change, a server-sent Canceled
is treated as a transient error and the backoff retry loop continues.
2026-05-04 11:59:25 +02:00
Zoltan Papp
a21f6ecb0a [client] release Status.mux before invoking notifier callbacks (#6039)
The Status recorder used to fire notifier callbacks while holding d.mux:
- notifyPeerListChanged / notifyPeerStateChangeListeners ran from inside
  the locked section of every Update*/AddPeerStateRoute/etc.
- notifyAddressChanged ran from UpdateLocalPeerState and CleanLocalPeerState
  while d.mux was held.
- onConnectionChanged was registered with a defer above defer d.mux.Unlock,
  so it executed before the mutex was released in the Mark*Connected/
  Disconnected helpers.
- notifyPeerStateChangeListeners did a blocking channel send under d.mux,
  so a slow subscriber stalled every other d.mux holder.

A listener that re-enters the recorder (e.g. calls GetFullStatus from
within a callback) deadlocks against d.mux, and any callback that takes
longer than expected stalls every other state query for its duration.

Capture the values needed for notification under the lock, release d.mux,
then call the notifier. Build per-peer router-state snapshots inside the
lock and dispatch them via dispatchRouterPeers afterwards. The router-peer
channel send stays blocking, but now happens outside d.mux so a slow
consumer cannot stall any other d.mux holder, and no peer state
transitions are silently dropped.

The notifier itself is unchanged: its internal state was already protected
by its own locks, and the field d.notifier is set once in NewRecorder and
never reassigned, so reading it without d.mux is safe.

Also fix a pre-existing race in Test_notifier_RemoveListener /
Test_notifier_SetListener: setListener spawns a goroutine that writes
listener.peers, but the tests read listener.peers without waiting for it.
2026-05-04 11:59:01 +02:00
Bethuel Mmbaga
6262b0d841 [management] Track pending approval in peer event metadata (#6040) 2026-05-04 12:47:13 +03:00
Viktor Liu
50b58a6828 [client, relay] Advertise relay server IP via signal for foreign-relay fallback dial (#6004) 2026-05-04 11:40:25 +02:00
Viktor Liu
057d651d2e [client, proxy] Add packet capture to debug bundle and CLI (#5891) 2026-05-04 11:28:56 +02:00
Misha Bragin
c4b2da4c92 [management] Add public connection ipv4 and ipv6 posture check (#6038)
This change enables admins to configure posture checks for connecting public IPs of their peers.

It changes the behavior of the check as well and now the evaluation is if the received network is part of the configured network.
2026-04-30 18:36:50 +02:00
Nicolas Frati
dcd1db42ef [management] Enable PAT creation during setup (#6003)
* enable pat creation on setup

* remove logic from handler towards setup service

* fix lint issue

* fix rollback on account id returning empty

* fix coderabbit comments

* fix setup PAT rollback behavior
2026-04-30 17:21:35 +02:00
Pascal Fischer
f29f5a0978 [management] add monitoring for nmap update source (#6036) 2026-04-30 14:52:54 +02:00
Zoltán Papp
88a2bf582d [client] Push-based status stream for the Wails UI
Adds a SubscribeStatus gRPC RPC that pushes a fresh FullStatus snapshot
on every peer-recorder state change, replacing the Wails UI's 2-second
Status poll. The daemon's notifier already triggers on Connected /
Disconnected / Connecting / management or signal flip / address
change / peers-list change; we now coalesce those into ticks on a
buffered chan and stream the resulting snapshots over gRPC.

- Status recorder gains SubscribeToStateChanges /
  UnsubscribeFromStateChanges + a non-blocking notifyStateChange that
  drops ticks when a subscriber's 1-slot buffer is full (next snapshot
  the consumer pulls already reflects everything).
- Server.Status handler split: the snapshot composition is shared
  with the new SubscribeStatus stream handler so unary and stream
  paths return identical bytes.
- UI peers service: pollLoop replaced by statusStreamLoop. The local
  name of the existing SubscribeEvents loop is now toastStreamLoop so
  the two streams are easy to tell apart — the underlying RPC name is
  unchanged.
- Tray applyStatus skips the icon refresh when connected/lastStatus
  hasn't changed; rapid SubscribeStatus bursts during health probes
  no longer churn Shell_NotifyIcon or the log.
2026-04-30 11:45:43 +02:00
Maycon Santos
3fc5a8d4a1 [misc] fix MSI generation add installer tests (#6031)
Add Windows installer build test workflow
v0.70.4
2026-04-29 23:44:38 +02:00
Zoltán Papp
0148d926d5 [client/ui-wails] Use original Fyne tray PNGs and drop the .ico split
The SVG-derived tray icons + multi-resolution .ico path looked correct on
disk but Wails3's Shell_NotifyIcon update never landed on the running
Windows tray — the icon stayed frozen on the .exe resource regardless of
how many times we called SetIcon. Single-PNG fed through the same path
updates correctly, so revert to the source-of-truth PNGs that ship with
the legacy Fyne UI and remove the icons_windows.go / tray_icon_*.go
split. The 6 colored tray PNGs and 6 macOS-template PNGs come from
client/ui/assets verbatim. Generation pipeline (assets/svg/) is gone.
2026-04-29 18:54:51 +02:00
Zoltan Papp
57945fc328 [client] Trigger mobile submodule bump PRs on release tags (#6029)
Trigger mobile submodule bump PRs on release tags
v0.70.3
2026-04-29 17:19:22 +02:00
Zoltán Papp
8f16a19b8f [client/ui-wails] Add windows:build:console task for log debugging
The default Windows build links the binary as a GUI subsystem app, so
stdout/stderr is detached from the launching terminal — invisible logrus
output makes tray and event-stream bugs hard to chase. Add a sibling task
that links as console subsystem and writes a separately-named binary so
the production output is preserved.

Usage:
  CGO_ENABLED=1 task windows:build:console
  bin\netbird-ui-console.exe   # logs print to the launching cmd/PowerShell
2026-04-29 16:21:45 +02:00
Viktor Liu
ed828b7af4 Tolerate EEXIST when adding macOS scoped default routes (#6027) 2026-04-29 16:08:47 +02:00
Viktor Liu
11ac2af2f5 Use BindListener for all userspace bind in lazyconn activity (#6028) 2026-04-29 16:07:33 +02:00
Bethuel Mmbaga
df197d5001 [management] Prevent JWT reuse during peer login (#6002) 2026-04-29 15:04:27 +03:00
shuuri-labs
ad93dcf980 [client] Enable UI autostart for silent and MSI installs (#6026)
* fix(client): enable UI autostart for silent and MSI installs

The MSI installer had no autostart logic and the EXE silent installer
skipped the autostart page, leaving the registry entry unwritten. This
caused the NetBird UI tray to not start at login after RMM deployments.

Add an AUTOSTART property (default: 1) to the MSI that writes the
HKLM Run key, and initialize AutostartEnabled in the NSIS .onInit so
silent installs match the interactive default.

* add real guid for NetBirdAutoStart component
2026-04-29 13:14:46 +02:00
Nicolas Frati
7eba5dafd8 [misc] Add comment automation on release workflow for PRs (#6016)
* feat: add comment automation on release workflow for PRs

* update action permissions
v0.70.2
2026-04-29 11:28:55 +02:00
Zoltán Papp
504dceedf3 [client] Add Wails3 + React desktop UI scaffold
Stage 1 of the client/ui (Fyne) replacement. Adds a new client/ui-wails
module that runs on Linux/macOS/Windows from a single React + Vite +
Tailwind frontend driven by a thin gRPC services layer in Go.

- Single-module integration (no submodule): merge Wails3 into root go.mod
  with build tags !android !ios !freebsd !js so cross-compiles on those
  targets exclude the package automatically.
- Seven gRPC-bound services: Connection, Settings, Networks, Profiles,
  Debug, Update, Peers. Peers bridges Status polling and SubscribeEvents
  to the Wails event bus (netbird:status, netbird:event).
- Tray + window shell mirrors the Fyne menu 1:1 with hide-on-close,
  SIGUSR1 / Windows named-event for external "show window" triggers.
- React pages cover functional parity for Status, Settings (3 tabs),
  Networks (3 tabs), Profiles, Debug, Update, QuickActions, LoginUrl.
- SVG-sourced tray icons (12 source SVGs incl. macOS template variants)
  rasterized to PNG via task common:generate:tray:icons.
- Linux launcher sets WEBKIT_DISABLE_DMABUF_RENDERER=1 in the .desktop
  Exec= line and in task linux:run so the app renders correctly under
  RDP, VirtualBox, KVM, and bare WMs (Fluxbox/dwm) without DRM access.
2026-04-29 11:10:23 +02:00
Viktor Liu
28fe26637b [client] Fix Windows installer upgrade detection for pre-0.70.1 installs (#6025) 2026-04-29 11:01:07 +02:00
Viktor Liu
407e9d304b [client] Move macOS sleep detection into the daemon (purego) (#5926) 2026-04-29 08:09:55 +02:00
Viktor Liu
e5474e199f [client] Use WinRT COM for Windows toasts (#6013)
* Use WinRT COM for Windows toasts instead of fyne's PowerShell path

* Quote autostart path and split HKCU registry into per-user component
v0.70.1
2026-04-28 20:54:06 +02:00
Bethuel Mmbaga
db44848e2d [management] Drop netmap calculation on peer read (#6006) 2026-04-28 18:25:56 +03:00
EL OUAZIZI Walid
9417ce3b3a fix(getting-started): Infinite healthcheck loop with existing traefik (#5871) 2026-04-28 17:22:51 +02:00
Zoltan Papp
8fc4265995 [relay] evict foreign client cache on disconnect (#6015)
* [relay] evict foreign client cache on disconnect

When a foreign relay's TCP connection drops, the manager's
onServerDisconnected handler only triggered reconnect logic for the
home server; the disconnected foreign entry stayed in the relayClients
cache. Subsequent OpenConn calls reused the closed client until the
60-second cleanup tick evicted it, breaking peer connectivity through
that relay for up to a minute.

Evict the foreign entry from the cache on disconnect so the next
OpenConn dials a fresh client.

Also:
- Make the reconnect backoff cap configurable via WithMaxBackoffInterval
  ManagerOption; the previous hard-coded 60s constant forced
  TestAutoReconnect to sleep ~61s. Test now polls Ready() and finishes
  in ~2s.
- Add NB_HOME_RELAY_SERVERS env var that overrides the relay URL list
  received from management, so a peer can be pinned to a specific home
  relay (used by the netbird-conn-lab Edge 4 reproducer).

* [client] treat empty NB_HOME_RELAY_SERVERS as unset

Returning (urls=[], ok=true) when the env var contained only separators or
whitespace caused callers to wipe the mgmt-provided relay list, leaving the
peer with no relays. Treat a parsed-empty result the same as an unset env.
2026-04-28 15:04:48 +02:00
Zoltan Papp
9c50819f20 Don't mark management disconnected on transient job stream errors (#6005)
The JOB stream is a separate channel from the SYNC stream. Server-side
EOF or other transient errors on the JOB stream do not indicate that
the management connection is unhealthy — the SYNC stream remains the
authoritative state signal.

Previously, a JOB stream EOF would call notifyDisconnected and the
client would emit OnConnecting to the UI. The backoff retry would
reconnect the JOB stream, but handleJobStream never calls notifyConnected
on success, so the UI was stuck on "Connecting" until the next SYNC
event or health check.

Keep notifyDisconnected for codes.PermissionDenied since IsLoginRequired
relies on managementError to detect expired auth.
2026-04-28 15:04:41 +02:00
Bethuel Mmbaga
6f0eff3ba0 [management] Handle single-string JWT group claim from IdPs (#6014) 2026-04-28 14:48:28 +03:00
Bethuel Mmbaga
f8745723fc [management] Add Microsoft AD FS support for embedded Dex identity providers (#6008) 2026-04-28 12:42:19 +03:00
Vlad
154b81645a [management] removed legacy network map code (#5565) 2026-04-27 16:02:54 +02:00
Maycon Santos
34167c8a16 [misc] Update release pipeline version (#5995) v0.70.0 2026-04-27 10:55:38 +02:00
Maycon Santos
d6f08e4840 [misc] Update sign pipeline version (#5981) 2026-04-24 13:13:27 +02:00
Zoltan Papp
f732b01a05 [management] unify peer-update test timeout via constant (#5952)
peerShouldReceiveUpdate waited 500ms for the expected update message,
and every outer wrapper across the management/server test suite paired
it with a 1s goroutine-drain timeout. Both were too tight for slower
CI runners (MySQL, FreeBSD, loaded sqlite), producing intermittent
"Timed out waiting for update message" failures in tests like
TestDNSAccountPeersUpdate, TestPeerAccountPeersUpdate, and
TestNameServerAccountPeersUpdate.

Introduce peerUpdateTimeout (5s) next to the helper and use it both in
the helper and in every outer wrapper so the two timeouts stay in sync.
Only runs down on failure; passing tests return as soon as the channel
delivers, so there is no slowdown on green runs.
2026-04-23 21:19:21 +02:00
alsruf36
c07c726ea7 [proxy] Set session cookie path to root (#5915) 2026-04-23 18:20:54 +02:00