Repository navigation
fix(desktop,web): advertise all usable network interfaces as selectable endpoints - #5165
William-BnCRocks wants to merge 3 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit be408765dc46133c4e0939e42758301e3e99e290. Configure here.
ApprovabilityVerdict: Needs human review This PR introduces significant runtime behavior changes—advertising multiple network interfaces instead of one, changing UI display, and altering preference key format. From an unvouched contributor, these user-facing changes warrant human review. You can customize Macroscope's approvability policy. Learn more. |
…le endpoints Network access previously advertised only the first non-internal IPv4 that os.networkInterfaces() enumerated, which on multi-homed machines (VPN + LAN) is often an address other devices cannot reach. Advertise one selectable endpoint per usable interface instead, re-resolved from live interfaces on each read, and give each endpoint a distinct default preference key so any interface can be chosen as the default. Fixes pingdotgg#2031
…keys Two configured HTTPS endpoints both labeled "Custom HTTPS" produced identical default-preference keys, so a stored default always resolved back to the first one. Include the endpoint host in the fallback key, matching the desktop-lan and tailscale-ip key shapes.
…ale endpoint provider Both enumeration sites now use the same isIpv4Family helper, so a tailnet address reported with a numeric family resolves as its tailscale-ip entry and dedupes instead of surfacing as a generic LAN endpoint.
2ec4b61 to
3ab2ef5
Compare
|
Note This comment is posted by Julius' dot Closing under the one-problem rule. Alongside advertising missing LAN interfaces, For reconsideration, split the manual-endpoint key change and its regression test into a separate PR. Keep the LAN enumeration, its required per-interface keys, and related tests together. |

What Changed
Settings → Connections → Network access advertised a single "Local network" endpoint: the first non-internal IPv4 that
os.networkInterfaces()happened to enumerate. On multi-homed machines (VPN + LAN) the VPN adapter often wins, and the addresses other devices can actually reach are never shown or selectable.Now every usable IPv4 interface is advertised as its own selectable endpoint:
resolveLanAdvertisedHost→resolveLanAdvertisedHosts: enumerates all non-internal, non-loopback, non-link-local IPv4 addresses with their interface names, deduped. Regular LAN/VPN addresses order ahead of Tailscale CGNAT addresses, so a real NIC wins the default while Tailnet-only machines keep working.desktop-lan:endpoint per address, labeled with the interface name — "Local network (en0)" — when more than one would show;isDefaultstays on the first.getAdvertisedEndpointsread, so a VPN connecting or dropping after launch is reflected on the settings UI's normal refresh. The backend already binds0.0.0.0in network-accessible mode, so any currently-present address is reachable.endpointDefaultPreferenceKeynow embedshost:portfordesktop-lan:/tailscale-ip:endpoints so each interface can individually be set as default. Previously all LAN endpoints collapsed to one key, so with several rows every one would have matched the stored default. A stored legacy key matches nothing and falls back to theisDefaultendpoint — no migration needed.family: 4fromos.networkInterfaces(), matching the existing normalizations instartupAccess.ts:41andDesktopBackendConfiguration.ts:348.The wire contract is unchanged:
DesktopServerExposureState.advertisedHost/endpointUrlstill carry the first host,T3CODE_DESKTOP_LAN_HOSTstill overrides to a single host, and "no usable address → fall back to local-only" behaves identically. Only the advertised-endpoints list grew.Verification: 5 new desktop tests (per-interface enumeration/labels/default, numeric family, tailnet dedupe with default transfer, cross-interface address dedupe, live interface changes) and 3 new web tests for the preference keys; full desktop suite 411 passing, web unit suite passing, typecheck and
vp checkclean.Why
Fixes #2031. On hosts with several interfaces (VPN/WireGuard + LAN), the auto-picked address is frequently one other devices can't reach, so the "Reachable at" note and copied pairing URLs need hand-editing. #2031 proposed a manual hostname override (#2086, closed as superseded by the endpoint catalog); the catalog can instead offer all interfaces directly, which keeps the copy/pairing flows working with zero typing and lets the user pick a different default per machine.
UI Changes
Before/after screenshots coming before this leaves draft: the Network access row previously listed one "Local network" entry; it now lists one entry per interface with the interface name, each selectable as default.
Checklist
Note
Advertise all usable network interfaces as selectable endpoints in desktop and web
resolveLanAdvertisedHostsinDesktopServerExposure.ts, which iterates all interfaces, filters to non-loopback IPv4 addresses, deduplicates by IP, and returns LAN addresses followed by Tailscale addresses.resolveDesktopCoreAdvertisedEndpointsnow emits oneAdvertisedEndpointper resolved LAN host; labels include the interface name (e.g. "Local network (en0)") when multiple non-Tailscale interfaces are present.getAdvertisedEndpointsre-reads interfaces on every call to reflect VPN/NIC changes without reconfiguration, and deduplicates LAN entries that share an IP with a Tailscale endpoint, transferring theisDefaultflag when needed.isIpv4Familyhelper inDesktopNetworkInterfaces.tsto treat numeric family4as IPv4, fixing Tailscale IP discovery in those environments.endpointDefaultPreferenceKeyinConnectionsSettings.logic.tsthat encodes host information in preference keys to avoid collisions between multiple LAN or Tailscale-IP endpoints sharing the same label.Macroscope summarized 3ab2ef5.
Note
Medium Risk
Changes how advertised LAN endpoints and stored default preferences are computed; multi-NIC users may see more endpoints and old single-key LAN defaults may not match until they pick a default again—pairing URL selection behavior is user-visible but bounded to network exposure settings.
Overview
Network-accessible desktop now discovers every usable IPv4 (non-internal, non-link-local, deduped), not just the first interface—so VPN + LAN machines get separate Local network rows (with interface names when there are multiple) and pairing/copy URLs can target the address peers can actually reach.
Desktop exposure re-resolves interfaces on each
getAdvertisedEndpointsread (VPN connect/disconnect), orders non-Tailscale addresses before tailnet IPs for the primary/default host, and drops duplicate LAN rows when Tailscale already advertises the same URL—movingisDefaultto the Tailscale entry.isIpv4Familycentralizes handling of Node’s numericfamily: 4.Web Connections moves pairing/default helpers into
ConnectionsSettings.logicand changesendpointDefaultPreferenceKeyto include host:port perdesktop-lan/tailscale-ipso each interface can be saved as default; legacy keys fall back to the marked default endpoint.Reviewed by Cursor Bugbot for commit 3ab2ef5. Bugbot is set up for automated code reviews on this repo. Configure here.