Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0cfbe37
Remove auto update check in initialization time
pappz Feb 24, 2026
3f8d872
[client] refactor: centralize auto-update logic in updatemanager
pappz Feb 24, 2026
6144cb5
[client] refactor: move update manager out of engine, start on GUI co…
pappz Feb 24, 2026
e837cb2
[client] refactor: introduce EngineServices struct to reduce NewEngin…
pappz Feb 25, 2026
0f0a7fe
Fix mobile build
pappz Feb 25, 2026
b230e49
Code cleaning
pappz Feb 25, 2026
40d0258
[client] refactor: improve update manager initialization and event ha…
pappz Feb 25, 2026
69acdc0
[client] improve update handling and notification logic
pappz Feb 25, 2026
98959b6
[client] Ignore cooldown in case of no force update
pappz Feb 25, 2026
5cc6040
Update the test for the new logic
pappz Feb 25, 2026
defcc35
Fix Android build
pappz Feb 25, 2026
e7ec0d8
Update client/internal/engine_ssh.go
pappz Feb 25, 2026
4c92bdc
[client] feat: add mutex to prevent concurrent installation attempts
pappz Feb 25, 2026
5404e0e
Update client/internal/updatemanager/manager_test_helpers_test.go
pappz Feb 26, 2026
ce01576
Merge remote-tracking branch 'refs/remotes/origin/refactor/auto-updat…
pappz Feb 26, 2026
bc46e0f
[client] fix: run update RPC in a goroutine to avoid blocking UI
pappz Feb 26, 2026
b1ac1ad
[test] fix: remove extraneous bracket, import missing strconv package
pappz Feb 26, 2026
ed96c54
[test] fix: increase waitForUpdateEvent timeout in tests for stability
pappz Feb 26, 2026
7580803
Update client/internal/updatemanager/supported_darwin.go
pappz Feb 26, 2026
40d6796
[test] fix: increase waitForUpdateEvent timeout in Linux tests for st…
pappz Feb 26, 2026
31b4c75
Merge remote-tracking branch 'refs/remotes/origin/refactor/auto-updat…
pappz Feb 26, 2026
78465a0
[client] fix: add mutex to prevent multiple service starts in update …
pappz Feb 26, 2026
c67c162
Update client/internal/updatemanager/manager_test.go
pappz Feb 26, 2026
159f73e
[client] refactor: inject auto-update support check into update manager
pappz Feb 26, 2026
ecdafa9
[client] refactor: use struct method for auto-update support check
pappz Feb 26, 2026
4967738
Remove unused function
pappz Mar 3, 2026
bac2bc8
Add comment
pappz Mar 3, 2026
cb92d3d
Fix grammar
pappz Mar 3, 2026
de2c24f
Remove unused function
pappz Mar 3, 2026
af669e1
[client] refactor: rename `updatemanager` package to `updater` for cl…
pappz Mar 3, 2026
29db262
Add documentation comment for NewManager function
pappz Mar 3, 2026
3db7b36
[client] fix: reorder variable assignments in update manager initiali…
pappz Mar 3, 2026
ba02af4
[client] fix: remove redundant update manager initialization check
pappz Mar 3, 2026
aff938d
[client] fix: disable update button during install request
pappz Mar 3, 2026
a4ae885
[client] docs: add comment for unused Stop method in update manager
pappz Mar 4, 2026
556d908
[client] fix: notify user of new version only once per enforced update
pappz Mar 10, 2026
88fabee
[client] fix: update NotifyUI logic to handle both download-only and …
pappz Mar 10, 2026
4e690be
Merge branch 'main' into refactor/auto-update
pappz Mar 10, 2026
2cb1c30
[client] fix: add timeout to context in auto-update support check
pappz Mar 10, 2026
8b8eb7f
Fix merge conflict
pappz Mar 10, 2026
2b9ac14
[management] Feature/auto update mgm (#5554)
pappz Mar 12, 2026
09f0c71
[client] fix: reserve field 3 in UpRequest message in daemon.proto
pappz Mar 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/android/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (c *Client) Run(platformFiles PlatformFiles, urlOpener URLOpener, isAndroid

// todo do not throw error in case of cancelled context
ctx = internal.CtxInitState(ctx)
c.connectClient = internal.NewConnectClient(ctx, cfg, c.recorder, false)
c.connectClient = internal.NewConnectClient(ctx, cfg, c.recorder)
return c.connectClient.RunOnAndroid(c.tunAdapter, c.iFaceDiscover, c.networkChangeListener, slices.Clone(dns.items), dnsReadyListener, stateFile)
}

Expand Down Expand Up @@ -157,7 +157,7 @@ func (c *Client) RunWithoutLogin(platformFiles PlatformFiles, dns *DNSList, dnsR

// todo do not throw error in case of cancelled context
ctx = internal.CtxInitState(ctx)
c.connectClient = internal.NewConnectClient(ctx, cfg, c.recorder, false)
c.connectClient = internal.NewConnectClient(ctx, cfg, c.recorder)
return c.connectClient.RunOnAndroid(c.tunAdapter, c.iFaceDiscover, c.networkChangeListener, slices.Clone(dns.items), dnsReadyListener, stateFile)
Comment thread
pappz marked this conversation as resolved.
}

Expand Down
2 changes: 1 addition & 1 deletion client/cmd/signer/artifactkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/spf13/cobra"

"github.com/netbirdio/netbird/client/internal/updatemanager/reposign"
"github.com/netbirdio/netbird/client/internal/updater/reposign"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/signer/artifactsign.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

"github.com/spf13/cobra"

"github.com/netbirdio/netbird/client/internal/updatemanager/reposign"
"github.com/netbirdio/netbird/client/internal/updater/reposign"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/signer/revocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/spf13/cobra"

"github.com/netbirdio/netbird/client/internal/updatemanager/reposign"
"github.com/netbirdio/netbird/client/internal/updater/reposign"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/signer/rootkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/spf13/cobra"

"github.com/netbirdio/netbird/client/internal/updatemanager/reposign"
"github.com/netbirdio/netbird/client/internal/updater/reposign"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command, activeProf *pr
r := peer.NewRecorder(config.ManagementURL.String())
r.GetFullStatus()

connectClient := internal.NewConnectClient(ctx, config, r, false)
connectClient := internal.NewConnectClient(ctx, config, r)
SetupDebugHandler(ctx, config, r, connectClient, "")

return connectClient.Run(nil, util.FindFirstLogPath(logFiles))
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/update_supported.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/netbirdio/netbird/client/internal/updatemanager/installer"
"github.com/netbirdio/netbird/client/internal/updater/installer"
"github.com/netbirdio/netbird/util"
)

Expand Down
2 changes: 1 addition & 1 deletion client/embed/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func (c *Client) Start(startCtx context.Context) error {
if err, _ := authClient.Login(ctx, c.setupKey, c.jwtToken); err != nil {
return fmt.Errorf("login: %w", err)
}
client := internal.NewConnectClient(ctx, c.config, c.recorder, false)
client := internal.NewConnectClient(ctx, c.config, c.recorder)
client.SetSyncResponsePersistence(true)

// either startup error (permanent backoff err) or nil err (successful engine up)
Expand Down
62 changes: 31 additions & 31 deletions client/internal/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import (
"github.com/netbirdio/netbird/client/internal/profilemanager"
"github.com/netbirdio/netbird/client/internal/statemanager"
"github.com/netbirdio/netbird/client/internal/stdnet"
"github.com/netbirdio/netbird/client/internal/updatemanager"
"github.com/netbirdio/netbird/client/internal/updatemanager/installer"
"github.com/netbirdio/netbird/client/internal/updater"
"github.com/netbirdio/netbird/client/internal/updater/installer"
nbnet "github.com/netbirdio/netbird/client/net"
cProto "github.com/netbirdio/netbird/client/proto"
"github.com/netbirdio/netbird/client/ssh"
Expand All @@ -44,13 +44,13 @@ import (
)

type ConnectClient struct {
ctx context.Context
config *profilemanager.Config
statusRecorder *peer.Status
doInitialAutoUpdate bool
ctx context.Context
config *profilemanager.Config
statusRecorder *peer.Status

engine *Engine
engineMutex sync.Mutex
engine *Engine
engineMutex sync.Mutex
updateManager *updater.Manager

persistSyncResponse bool
}
Expand All @@ -59,17 +59,19 @@ func NewConnectClient(
ctx context.Context,
config *profilemanager.Config,
statusRecorder *peer.Status,
doInitalAutoUpdate bool,
) *ConnectClient {
return &ConnectClient{
ctx: ctx,
config: config,
statusRecorder: statusRecorder,
doInitialAutoUpdate: doInitalAutoUpdate,
engineMutex: sync.Mutex{},
ctx: ctx,
config: config,
statusRecorder: statusRecorder,
engineMutex: sync.Mutex{},
}
}

func (c *ConnectClient) SetUpdateManager(um *updater.Manager) {
c.updateManager = um
}

// Run with main logic.
func (c *ConnectClient) Run(runningChan chan struct{}, logPath string) error {
return c.run(MobileDependency{}, runningChan, logPath)
Expand Down Expand Up @@ -187,14 +189,13 @@ func (c *ConnectClient) run(mobileDependency MobileDependency, runningChan chan
stateManager := statemanager.New(path)
stateManager.RegisterState(&sshconfig.ShutdownState{})

updateManager, err := updatemanager.NewManager(c.statusRecorder, stateManager)
if err == nil {
updateManager.CheckUpdateSuccess(c.ctx)
if c.updateManager != nil {
c.updateManager.CheckUpdateSuccess(c.ctx)
}

inst := installer.New()
if err := inst.CleanUpInstallerFiles(); err != nil {
log.Errorf("failed to clean up temporary installer file: %v", err)
}
inst := installer.New()
if err := inst.CleanUpInstallerFiles(); err != nil {
log.Errorf("failed to clean up temporary installer file: %v", err)
}

defer c.statusRecorder.ClientStop()
Expand Down Expand Up @@ -308,7 +309,15 @@ func (c *ConnectClient) run(mobileDependency MobileDependency, runningChan chan
checks := loginResp.GetChecks()

c.engineMutex.Lock()
engine := NewEngine(engineCtx, cancel, signalClient, mgmClient, relayManager, engineConfig, mobileDependency, c.statusRecorder, checks, stateManager)
engine := NewEngine(engineCtx, cancel, engineConfig, EngineServices{
SignalClient: signalClient,
MgmClient: mgmClient,
RelayManager: relayManager,
StatusRecorder: c.statusRecorder,
Checks: checks,
StateManager: stateManager,
UpdateManager: c.updateManager,
}, mobileDependency)
engine.SetSyncResponsePersistence(c.persistSyncResponse)
c.engine = engine
c.engineMutex.Unlock()
Expand All @@ -318,15 +327,6 @@ func (c *ConnectClient) run(mobileDependency MobileDependency, runningChan chan
return wrapErr(err)
}

if loginResp.PeerConfig != nil && loginResp.PeerConfig.AutoUpdate != nil {
// AutoUpdate will be true when the user click on "Connect" menu on the UI
if c.doInitialAutoUpdate {
log.Infof("start engine by ui, run auto-update check")
c.engine.InitialUpdateHandling(loginResp.PeerConfig.AutoUpdate)
c.doInitialAutoUpdate = false
}
}

log.Infof("Netbird engine started, the IP is: %s", peerConfig.GetAddress())
state.Set(StatusConnected)

Expand Down
2 changes: 1 addition & 1 deletion client/internal/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/netbirdio/netbird/client/anonymize"
"github.com/netbirdio/netbird/client/internal/peer"
"github.com/netbirdio/netbird/client/internal/profilemanager"
"github.com/netbirdio/netbird/client/internal/updatemanager/installer"
"github.com/netbirdio/netbird/client/internal/updater/installer"
nbstatus "github.com/netbirdio/netbird/client/status"
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
"github.com/netbirdio/netbird/util"
Expand Down
80 changes: 31 additions & 49 deletions client/internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import (
"github.com/netbirdio/netbird/client/internal/routemanager"
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
"github.com/netbirdio/netbird/client/internal/statemanager"
"github.com/netbirdio/netbird/client/internal/updatemanager"
"github.com/netbirdio/netbird/client/internal/updater"
"github.com/netbirdio/netbird/client/jobexec"
cProto "github.com/netbirdio/netbird/client/proto"
"github.com/netbirdio/netbird/client/system"
Expand Down Expand Up @@ -79,7 +79,6 @@ const (

var ErrResetConnection = fmt.Errorf("reset connection")

// EngineConfig is a config for the Engine
type EngineConfig struct {
WgPort int
WgIfaceName string
Expand Down Expand Up @@ -141,6 +140,17 @@ type EngineConfig struct {
LogPath string
}

// EngineServices holds the external service dependencies required by the Engine.
type EngineServices struct {
SignalClient signal.Client
MgmClient mgm.Client
RelayManager *relayClient.Manager
StatusRecorder *peer.Status
Checks []*mgmProto.Checks
StateManager *statemanager.Manager
UpdateManager *updater.Manager
}

// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
type Engine struct {
// signal is a Signal Service client
Expand Down Expand Up @@ -209,7 +219,7 @@ type Engine struct {
flowManager nftypes.FlowManager

// auto-update
updateManager *updatemanager.Manager
updateManager *updater.Manager

// WireGuard interface monitor
wgIfaceMonitor *WGIfaceMonitor
Expand Down Expand Up @@ -239,34 +249,30 @@ type localIpUpdater interface {
func NewEngine(
clientCtx context.Context,
clientCancel context.CancelFunc,
signalClient signal.Client,
mgmClient mgm.Client,
relayManager *relayClient.Manager,
config *EngineConfig,
services EngineServices,
mobileDep MobileDependency,
statusRecorder *peer.Status,
checks []*mgmProto.Checks,
stateManager *statemanager.Manager,
) *Engine {
engine := &Engine{
clientCtx: clientCtx,
clientCancel: clientCancel,
signal: signalClient,
signaler: peer.NewSignaler(signalClient, config.WgPrivateKey),
mgmClient: mgmClient,
relayManager: relayManager,
signal: services.SignalClient,
signaler: peer.NewSignaler(services.SignalClient, config.WgPrivateKey),
mgmClient: services.MgmClient,
relayManager: services.RelayManager,
peerStore: peerstore.NewConnStore(),
syncMsgMux: &sync.Mutex{},
config: config,
mobileDep: mobileDep,
STUNs: []*stun.URI{},
TURNs: []*stun.URI{},
networkSerial: 0,
statusRecorder: statusRecorder,
stateManager: stateManager,
checks: checks,
statusRecorder: services.StatusRecorder,
stateManager: services.StateManager,
checks: services.Checks,
probeStunTurn: relay.NewStunTurnProbe(relay.DefaultCacheTTL),
jobExecutor: jobexec.NewExecutor(),
updateManager: services.UpdateManager,
}

log.Infof("I am: %s", config.WgPrivateKey.PublicKey().String())
Expand Down Expand Up @@ -309,7 +315,7 @@ func (e *Engine) Stop() error {
}

if e.updateManager != nil {
e.updateManager.Stop()
e.updateManager.SetDownloadOnly()
}
Comment thread
pappz marked this conversation as resolved.

log.Info("cleaning up status recorder states")
Expand Down Expand Up @@ -559,13 +565,6 @@ func (e *Engine) Start(netbirdConfig *mgmProto.NetbirdConfig, mgmtURL *url.URL)
return nil
}

func (e *Engine) InitialUpdateHandling(autoUpdateSettings *mgmProto.AutoUpdateSettings) {
e.syncMsgMux.Lock()
defer e.syncMsgMux.Unlock()

e.handleAutoUpdateVersion(autoUpdateSettings, true)
}

func (e *Engine) createFirewall() error {
if e.config.DisableFirewall {
log.Infof("firewall is disabled")
Expand Down Expand Up @@ -793,39 +792,22 @@ func (e *Engine) PopulateNetbirdConfig(netbirdConfig *mgmProto.NetbirdConfig, mg
return nil
}

func (e *Engine) handleAutoUpdateVersion(autoUpdateSettings *mgmProto.AutoUpdateSettings, initialCheck bool) {
if autoUpdateSettings == nil {
func (e *Engine) handleAutoUpdateVersion(autoUpdateSettings *mgmProto.AutoUpdateSettings) {
if e.updateManager == nil {
return
}

disabled := autoUpdateSettings.Version == disableAutoUpdate

// stop and cleanup if disabled
if e.updateManager != nil && disabled {
log.Infof("auto-update is disabled, stopping update manager")
e.updateManager.Stop()
e.updateManager = nil
if autoUpdateSettings == nil {
return
}

// Skip check unless AlwaysUpdate is enabled or this is the initial check at startup
if !autoUpdateSettings.AlwaysUpdate && !initialCheck {
log.Debugf("skipping auto-update check, AlwaysUpdate is false and this is not the initial check")
if autoUpdateSettings.Version == disableAutoUpdate {
log.Infof("auto-update is disabled")
e.updateManager.SetDownloadOnly()
return
Comment thread
pappz marked this conversation as resolved.
}

// Start manager if needed
if e.updateManager == nil {
log.Infof("starting auto-update manager")
updateManager, err := updatemanager.NewManager(e.statusRecorder, e.stateManager)
if err != nil {
return
}
e.updateManager = updateManager
e.updateManager.Start(e.ctx)
}
log.Infof("handling auto-update version: %s", autoUpdateSettings.Version)
e.updateManager.SetVersion(autoUpdateSettings.Version)
e.updateManager.SetVersion(autoUpdateSettings.Version, autoUpdateSettings.AlwaysUpdate)
}

func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
Expand All @@ -842,7 +824,7 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
}

if update.NetworkMap != nil && update.NetworkMap.PeerConfig != nil {
e.handleAutoUpdateVersion(update.NetworkMap.PeerConfig.AutoUpdate, false)
e.handleAutoUpdateVersion(update.NetworkMap.PeerConfig.AutoUpdate)
}

if update.GetNetbirdConfig() != nil {
Expand Down
Loading
Loading