Address golangci-lint findings in users_test.go: replace inline
"if err := ...; err != nil" statements with plain assignments
(noinlineerr) and add blank lines between statements in the fake
server's filter loop and before an early return (wsl_v5).
resolveSingleUser returned the raw --identifier flag value instead of
the identifier of the matched user. Renaming with --name therefore sent
OldId=0 to the API and failed with "user not found". Return the matched
user's identifier and pass it straight to the rename endpoint.
After Remove/Rename, the extra-records filewatcher retried with
context.Background and the default 15-minute backoff budget, so Close
could not stop Run. Cancel that retry when closeCh closes. If the file
is still missing after the budget, watch the parent directory so a later
recreate is seen.
Close the fsnotify watcher on NewExtraRecordsManager error paths after
NewWatcher succeeds.
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Serve stored a Background context for tailsql and called
context.Done() during signal shutdown. Done only returns the
done channel and does not cancel, so tailsql never stopped
when Headscale shut down.
Create a cancellable child of the Serve context, run
`runTailSQLService` in the listener errgroup so its error is
surfaced, and call the cancel func on shutdown - tailsql
unblocks on ctx.Done.
The steps now open the Tailscale app first to install the VPN
configuration, which contradicted the warning against opening the app
after installation. The actual constraint is not signing in before the
headscale URL is set.
The instructions are duplicated between the docs and the HTML page
headscale serves at /apple. Reorder the tvOS steps there to match, so
the VPN configuration is installed before the alternate coordination
server URL is set.
The instructions didn't work for tvOS 26.6 / Tailscale 1.102.2. When the `ALTERNATE COORDINATION SERVER URL` is set, the `Install VPN Configuration` breaks.
Clicking does nothing and the tvOS app logs showed `addUser: backendManager does not exist`.
Instead I first started tailscale and installed the vpn profile and then add the headscale url and then signed. Which seemed to have worked
Fix the inverted HTTP metrics skip condition, which caused the collector to ignore all requests except OPTIONS.
Apply the correction to both the main and Noise routers so regular HTTP traffic is included in http_requests_total and http_request_duration_seconds.
PR tailscale/tailscale#20646 changed the representation of DERP region
IDs from plain ints to a tailcfg.DERPRegionID type. This patch
requires that version of the tailscale.com library and updates our
code to also use the new type.
Updates: tailscale/tailscale#20165
(cherry picked from commit 79695ab51b)
Go 1.27 collapses requires into one direct and one indirect block, so the
modernc lockstep note has to live inside a block to survive tidy.
-compat=1.27 is a no-op now that the go directive is 1.27.
Go 1.27 allows setting promoted fields of embedded structs directly in
composite literals, so gorm.Model wrappers go away. Plus strings.Cut,
errors.AsType, reflect.TypeAssert and one gofumpt nit.
tailscale.com v1.103.0-pre drops the "format" struct tags that Go 1.27's
finalized encoding/json/v2 rejects; without it MapResponse marshaling
fails for any tailnet with an SSH policy.
Use buildGoLatestModule and go_latest so a Go release bump is a
flake.lock update, not a flake.nix edit. Drop the vendored
golangci-lint derivation, now current in nixpkgs.
waitForFollowup selected on ctx.Done() and the verdict channel with equal
priority; when both were ready, select picked at random and discarded a
successful registration as a spurious 401 timeout. Check for a completed
verdict first, race the deadline only if none is ready.
Fixes#3385
With node.ephemeral.inactivity_timeout set, ephemeral nodes are
usually deleted after they go offline, but under reconnect churn some
departed nodes stayed in the node list as disconnected indefinitely
until removed manually or until Headscale restarted.
Ephemeral cleanup is timer-based via EphemeralGarbageCollector, not a
periodic LastSeen scan. serveLongPoll cancelled any pending GC timer
at the very start of a long-poll attempt and only rescheduled on a
clean disconnect after Connect. If a reconnect cancelled the timer and
then failed before Connect (for example an UpdateNodeFromMapRequest
error), the deferred cleanup saw connectGen == 0 and returned without
Schedule. The node remained offline with no deletion timer and no
reconciler to recover it.
Cancel the ephemeral GC timer only after a successful Connect, so a
failed reconnect leaves an already-armed inactivity timer intact.
Successful reconnects still cancel GC once the node is online, and a
later disconnect reschedules as before.
Add TestFailedReconnectDoesNotCancelEphemeralGC to lock in the
ordering, plus IsScheduled and DeleteNodeFromStoreForTest helpers for
the test.
Fixes#3382
Co-authored-by: Cursor <cursoragent@cursor.com>