tailscale / tailscale/tailscale

ipn/ipnserver: remove Windows special cases, serve status immediately for GUI

Open
#6,522 0 comments 0 reactions 0 assignees View on GitHub
needs-fix OS-windows
Dominant language
Go
Stars
36.5k
Forks
3.2k
Avg merge
1d 23h
Merged PRs (30d)
132

Description

All platforms except Windows use `ipnserver.New` followed by `ipnserver.(*Server).Run`.

But `ipnserver.New` requires a `wgengine.Engine` and creating one on Windows can fail and required (actually: still requires) retries, so on Windows we use `ipnserver.Run` which takes a `getEngine func() (wgengine.Engine, *netstack.Impl, error)` argument instead, and then we retry the `getEngine` call as needed on each connection. That means the Windows GUI's reconnect loop (with backoff) loop eventually maybe gets a good one, and then we stick with using that `wgengine.Engine` (via the also-Windows-only `getEngineUntilItWorksWrapper` code).

It's all pretty hacky, and I don't like one platform being special-cased.

Even with the hack, the ipnserver still doesn't start up right away and the GUI says something like "Tailscale service not running", which isn't true. It's running but hanging to create a tun device.

Instead, we should start up the IPN HTTP server immediately (on all platforms) and create the engine async (on all platforms), and only block `/localapi/` HTTP request until the engine is created. Then we can add an always-serving ipnserver HTTP handler at like `/status` that returns a status enum + message for a Status of {Starting,Ready,PermanentlyFailed} and the Windows GUI can use that. Or maybe we continue to serve the WatchIPNBus handler even without an engine and serve those status messages over ipn.Notify.

In any case, this is a tracking bug to both:

1) unify the Windows and non-Windows ipnserver start-up paths,
2) make the Windows GUI not get blocked by wgengine.Engine creation and have it show what's actually happening. It shouldn't say the Tailscale Service is dead if it's not.

We should do all this even if we make the Windows wintun start-up consistently work, because even when it works, it can be slow (5-10 seconds) when the wintun driver hasn't even been installed and we want the post-installer first time experience of starting the Tailscale Windows GUI to not have "Service not running" errors for 5-10 seconds. But even if that were made fast, we still want to get rid of the `ipnserver.Run` entrypoint and have Windows use the same API has the other platforms.

/cc @andrew-d @maisem @dblohm7

Contributor guide

Open the contributing guide

Research direction

Start by tracing the ipnserver.New, Server.Run, and Windows-only ipnserver.Run entry points, including wgengine.Engine creation and the Windows GUI reconnect loop. Review the existing /localapi/ and WatchIPNBus handlers, then define how /status or ipn.Notify should report Starting, Ready, and PermanentlyFailed. Done means startup paths are unified and the GUI no longer reports the service as stopped while engine creation is pending.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend, networking, operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.