378 Commits

Author SHA1 Message Date
Aarnav Tale b3c0c1c691 fix(agent): always spawn agent with pre-auth key and auto-approve
- Generate a fresh pre-auth key for every agent startup
- Preserve existing tailscale state to avoid creating a new host
- Auto-approve pending auth requests via /api/v1/auth/approve
- Show approval link in settings UI as fallback

Closes HP-558
2026-07-13 11:00:43 -04:00
Sandro 3d9b9b0f7e Fix typo url in code to docs (#586) 2026-07-12 18:20:07 -04:00
Aarnav Tale 1345b7ca13 fix(ui): fix assigning ACL tags to non-user nodes 2026-07-04 00:50:57 -04:00
Aarnav Tale 948cfad58c fix: handle registration keys on headscale 0.29+
Closes HP-555.
2026-07-04 00:07:53 -04:00
Aarnav Tale 990e1e9ff5 chore(ssh): warn about broken SSH on certain versions 2026-07-01 11:23:35 -04:00
Aarnav Tale 18263e4878 fix(ui): show display names in lists
Closes HP-549.
2026-06-22 20:23:41 -04:00
Aarnav Tale 0439175e73 feat(auth): support role sync on re-login 2026-06-22 16:40:29 -04:00
Aarnav Tale a3cd8444a3 chore(auth): add more informative logs 2026-06-22 16:40:29 -04:00
Aarnav Tale dc32427cff feat(config): use minimal headscale config 2026-06-22 16:40:28 -04:00
Aarnav Tale 5d6eef5843 feat: update to the v8 middleware api 2026-06-20 12:38:09 -04:00
Aarnav Tale 3f9dcd5eb4 feat: update build for react router v8 2026-06-20 12:09:42 -04:00
Aarnav Tale 0c4d175eb7 feat(auth): support deriving roles from the IDP
Closes HP-352.
2026-06-20 11:53:09 -04:00
Aarnav Tale 96f2721272 feat(auth): support reverse-proxy driven proxy auth
Closes HP-353.
2026-06-20 11:41:44 -04:00
Aarnav Tale 57c8046f99 feat(ui): add support for showing existing tag options 2026-06-17 11:35:38 -04:00
Aarnav Tale 8017436bb6 fix(ui): increase ssh pre-auth key expiry time and present errors
Closes HP-546
2026-06-17 11:27:07 -04:00
Aarnav Tale dea19f9330 fix(ui): validate machine names before rename submission
Closes HP-545
2026-06-17 11:15:30 -04:00
Aarnav Tale 8c508e0602 feat(users): expose rename and delete for unlinked Headscale users
The user-actions handler already supported `rename_user` and
`delete_user` (both keyed by headscale_user_id), but the Unlinked
Headscale Users table had no menu to invoke them. That left admins
with no UI path to remove or rename Headscale users that have no
Headplane counterpart — e.g. users created via the Headscale CLI
before an OIDC migration.

Wire the existing dialogs into a new HeadscaleUserMenu rendered in
the row's actions column. OIDC-managed users still can't be renamed
(Headscale rejects it), so the Rename item hides for those.

Closes #525

Amp-Thread-ID: https://ampcode.com/threads/T-019e7ae4-6862-760c-a3e7-239350eab71d
Co-authored-by: Amp <amp@ampcode.com>
2026-05-30 18:49:27 -04:00
Aarnav Tale 0a51182eed fix(pre-auth-keys): pass Headscale numeric user id when expiring on 0.27.x
The pre-0.28 ExpirePreAuthKey RPC takes a uint64 `user` field plus the
key string. The API layer reads that uint64 from `key.user?.id`, but
the action was wrapping the form's user_id as `{ name: user }` — so
.id was always undefined and the wire request sent an empty string,
which Headscale rejects with "proto: invalid value for uint64 field
user". 0.28+ is unaffected because the new expire endpoint only reads
`key.id` (the stable preauthkey id).

Pass `{ id: user }` so the numeric Headscale user id reaches the wire.

Amp-Thread-ID: https://ampcode.com/threads/T-019e7ae4-6862-760c-a3e7-239350eab71d
Co-authored-by: Amp <amp@ampcode.com>
2026-05-30 18:49:11 -04:00
Aarnav Tale 22a521dff5 fix(machines): register node by Headscale username, not numeric id
Headscale's RegisterNodeRequest.user proto field is a string that the
RegisterNode handler resolves with GetUserByName (a strict WHERE name=?
SQL match) — there is no numeric-id fallback. The Owner select in the
Register Machine Key dialog was sending user.id, so registration failed
with ErrUserNotFound whenever the display name and the numeric id
disagreed (which is always for unlinked Headscale users).

Send user.name instead.

Closes #532

Amp-Thread-ID: https://ampcode.com/threads/T-019e7ae4-6862-760c-a3e7-239350eab71d
Co-authored-by: Amp <amp@ampcode.com>
2026-05-30 18:48:57 -04:00
Aarnav Tale d7f1d665a4 feat: bump headscale minimum to 0.27 2026-05-30 17:32:00 -04:00
Aarnav Tale 7901f37002 fix: correctly handle user id passthrough on headscale actions 2026-05-30 17:14:28 -04:00
Aarnav Tale 56c5e5ac8c feat: make api calls more resilient and stuff 2026-05-25 17:14:26 -04:00
Aarnav Tale 0512565f8e feat: replace openapi hashing system with /version
Apparently I didn't use my brain cells and rely on the /version
endpoint that Headscale has exposed since 0.26 (our lowest supported
version). Switching to that significantly simplifies the API surface.
2026-05-25 11:51:02 -04:00
Aarnav Tale d4eee702e9 refactor(server): replace AppContext undefined sentinels with Feature<T>
Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019e5550-4435-7118-8393-cdcc97042178
2026-05-23 16:56:34 -04:00
Aarnav Tale deb284e2b4 feat: ditch hono 2026-04-26 23:52:49 -04:00
Aarnav Tale 5a2098eea5 chore: format everything with oxfmt 2026-04-26 20:38:45 -04:00
Aarnav Tale b961b339bb feat: add support for OIDC logouts
Closes HP-407.
2026-04-26 20:36:52 -04:00
Aarnav Tale ac6f9e4f7e feat: support toggling light or dark color schemes
Fixes HP-375.
2026-04-26 20:33:48 -04:00
Aarnav Tale fccd2eefc4 feat: pull local endpoints/addresses from host info 2026-04-11 12:25:17 -04:00
Aarnav Tale 93be180479 Merge pull request #527 from eccgecko/fix/zero-time-expiry-display 2026-04-10 22:04:26 -04:00
Aarnav Tale f0f02b3c4c fix: remove unnecessary remix-utils dependency 2026-04-10 21:01:07 -04:00
Aarnav Tale c030d1fbe4 feat: de-uglify the ACL editor 2026-04-10 21:00:52 -04:00
eccgecko c164e07336 fix: show 'Never' for Go zero-time expiry on detail page
The 'Key expiry' attribute only checked node.expiry !== null, showing a
garbled date for the '0001-01-01T00:00:00Z' zero-time that headscale
may return for tagged nodes (juanfont/headscale#3170).
2026-04-11 00:08:28 +01:00
eccgecko d26c23313c fix: show "No expiry" badge for Go zero-time expiry
uiTagsForNode() only checked node.expiry === null, missing Go
zero-time that headscale returns for tagged nodes after a
restart (juanfont/headscale#3170).

The !node.expired guard is technically redundant with isNoExpiry but
documents intent: "No expiry" is only shown for nodes that never
had an expiry set
2026-04-11 00:07:32 +01:00
Aarnav Tale a0b2077c7b chore: remove faker-js dependency 2026-04-09 21:57:46 -04:00
Aarnav Tale 0f19fdf0da feat: rebuild browser ssh from the ground up 2026-04-09 21:56:42 -04:00
Aarnav Tale d255098128 fix: make the ssh button look nicer 2026-04-07 00:36:04 -04:00
Aarnav Tale 33f7bbb0cf fix: handle empty ACLs 2026-04-07 00:24:50 -04:00
Aarnav Tale 10278d0cc9 fix: correctly expire pre-auth-keys in 0.28.0+ 2026-04-07 00:24:50 -04:00
Aarnav Tale bdcd4c5bad Merge pull request #518 from Kroppeb/fix/wrong-url-in-help-message 2026-04-06 21:42:48 -04:00
Aarnav Tale 61e7303363 fix: handle URI components in provider ID 2026-04-06 21:19:27 -04:00
Aarnav Tale 1259642f8a feat: replace openid-client with clean-room oidc system 2026-04-03 16:36:27 -04:00
Aarnav Tale 4cd0c1e206 fix: use headscale.api_key where possible 2026-04-03 16:34:50 -04:00
Robbe Pincket b2dfa773b0 fix: change oidc config error notice url 2026-04-01 22:17:11 +02:00
Aarnav Tale 838a2cd732 fix: store profile picture in db to prevent header overload 2026-03-30 13:58:29 -04:00
Aarnav Tale 9ac3ab1861 Merge pull request #507 from siemenvdn/feature/extend-machine-filtering
Add additional Machines list filters
2026-03-29 20:29:33 -04:00
Siemen Van den Neste 44f45c396c fix: update user filtering to use user name instead of user ID 2026-03-29 20:37:18 +02:00
Aarnav Tale ee59a2d06d feat: switch agent to a periodic dump rather than long running process 2026-03-27 13:32:59 -04:00
Aarnav Tale 2c57187628 feat: switch to a generalized api key config 2026-03-27 13:32:59 -04:00
Aarnav Tale 131c54f501 fix: correctly re-enqueue event stream controller when closed 2026-03-26 12:58:35 -04:00