elem-go does not escape attribute values, so the raw query reaches
the rendered HTML verbatim. Pre-escape with html.EscapeString to prevent
reflected XSS.
Updates #3157
- Remove redundant inline button/input styles that duplicate CSS
- Use CSS variables for input (dark mode support)
- Use A(), Ul(), Ol(), P() wrappers from general.go
- Add expandable explanation of what the ping tests
- Fix section spacing rhythm (spaceXL before results, space2XL
before connected nodes)
- Add flex-wrap for mobile responsiveness
Add a reusable <details>/<summary> component to the shared design
system. Styled to match the existing card/box component family
(border, radius, CSS variables for dark mode).
Collapsed by default with a clickable summary line.
Implement tailcfg.PingRequest support so the control server can verify
whether a connected node is still reachable. This is the foundation for
faster offline detection (currently ~16min due to Go HTTP/2 TCP retransmit
behavior) and future C2N communication.
The server sends a PingRequest via MapResponse with a unique callback
URL. The Tailscale client responds with a HEAD request to that URL,
proving connectivity. Round-trip latency is measured.
Wire PingRequest through the Change → Batcher → MapResponse pipeline,
add a ping tracker on State for correlating requests with responses,
add ResolveNode for looking up nodes by ID/IP/hostname, and expose a
/debug/ping page (elem-go form UI) and /machine/ping-response endpoint.
Updates #2902
Updates #2129
Replace the bullet list of device details with a two-column table
for cleaner visual hierarchy. Labels are bold and left-aligned,
values right-aligned with subtle row separators. The machine key
value uses an inline code style.
Updates juanfont/headscale#3182
Tighten the SVG viewBox to the actual content bounding box and
remove hardcoded width/height attributes so the browser no longer
adds horizontal padding via preserveAspectRatio. The "h" wordmark
now left-aligns with the page content below it.
Replace the error icon SVG path (which had an off-center X) with
a simple circle + two crossed lines drawn from a centered viewBox.
Both icons now use fill="currentColor" for dark mode adaptation.
Updates juanfont/headscale#3182
Replace hardcoded Go color constants with var(--hs-*) and
var(--md-*) CSS custom properties in externalLink, orDivider,
card, warningBox, downloadButton, and pageFooter. This ensures
all components follow the dark mode theme automatically.
Also switch pageFooter from div to semantic footer element and
simplify externalLink by letting CSS handle link styling.
Updates juanfont/headscale#3182
Bump base font size from 0.8rem to 1rem (16px) to meet mobile
accessibility guidelines and avoid iOS auto-zoom on inputs.
Add CSS custom properties for all theme colors with a
prefers-color-scheme: dark media query so pages adapt to OS dark
mode. Component inline styles reference var(--hs-*) tokens so they
follow the scheme automatically.
Accessibility improvements:
- role="status" + aria-live="polite" on success boxes
- role="alert" + aria-live="assertive" on error boxes
- role="note" on warning boxes
- Visible focus rings via :focus-visible
- Link underlines (don't rely on color alone)
- SVG icons use currentColor for theme adaptation
- prefers-reduced-motion media query
- <main> landmark element wrapping page content
- Button styling with 44px min-height touch target
- List item spacing
Updates juanfont/headscale#3182
Add errorBox() and errorIcon() to the design system, mirroring the
existing successBox()/checkboxIcon() pattern with red error styling.
Extract error color constants from the inline values in statusMessage().
Add AuthError() template that renders a styled HTML error page using
the same HtmlStructure/mdTypesetBody/logo/footer as all other
browser-facing pages.
Updates juanfont/headscale#3182
Render an interstitial showing device hostname, OS, and machine-key
fingerprint before finalising OIDC registration. The user must POST
to /register/confirm/{auth_id} with a CSRF double-submit cookie.
Removes the TODO at oidc.go:201.
Extract shared HTML/CSS design into a common template and create
generalised auth success and web auth templates that work for both
node registration and SSH check authentication flows.
Updates #1850
Generalise the registration pipeline to a more general auth pipeline
supporting both node registrations and SSH check auth requests.
Rename RegistrationID to AuthID, unexport AuthRequest fields, and
introduce AuthVerdict to unify the auth finish API.
Add the urlParam generic helper for extracting typed URL parameters
from chi routes, used by the new auth request handler.
Updates #1850
Move favicon.png, style.css, and headscale.svg to hscontrol/assets/
and create a single assets.go file with all embed directives.
Update hscontrol/handlers.go and hscontrol/templates/general.go to
use the centralized assets package.
Refactor template system to use go:embed for external assets and
CSS classes for styling instead of inline styles:
- general.go: Add go:embed directives for style.css and headscale.svg,
replace inline styles with CSS classes (H1, H2, H3, P, etc.),
add mdTypesetBody wrapper with Material for MkDocs styling
- apple.go, oidc_callback.go, register_web.go, windows.go:
Update to use new CSS-based helper functions (H1, H2, P, etc.)
and mdTypesetBody for consistent layout
This separates content from presentation, making templates easier
to maintain and update. All styling is now centralized in style.css
with Material for MkDocs design system.
Add design system assets for HTML templates:
- headscale.svg: Logo with optimized viewBox for proper alignment
- style.css: Material for MkDocs CSS variables and typography
- design.go: Design system constants for consistent styling
The logo viewBox is adjusted to 32.92 0 1247.08 640 to eliminate
whitespace from the original export and ensure left alignment with
text content.
Replace html/template with type-safe elem-go templating for OIDC
callback page. Improves consistency with other templates and provides
compile-time safety. All UI elements and styling preserved.
Build / build-cross (GOARCH=386 GOOS=linux) (push) Waiting to run
Build / build-cross (GOARCH=amd64 GOOS=darwin) (push) Waiting to run
Build / build-cross (GOARCH=amd64 GOOS=linux) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=5) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=6) (push) Waiting to run
Build / build-cross (GOARCH=arm GOOS=linux GOARM=7) (push) Waiting to run
Build / build-cross (GOARCH=arm64 GOOS=darwin) (push) Waiting to run
Build / build-cross (GOARCH=arm64 GOOS=linux) (push) Waiting to run
Tests / test (push) Waiting to run
This change makes editing the generated command easier.
For example, after pasting into a terminal, the cursor position will be
near the username portion which requires editing.
* Changed all the HTML into go using go-elem
Created templates package in ./hscontrol/templates.
Moved the registerWebAPITemplate into the templates package as a function to be called.
Replaced the apple and windows html files with go-elem.
* update flake
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
---------
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
Co-authored-by: Kristoffer Dalby <kristoffer@tailscale.com>
* Rename docs/ios-client.md to docs/apple-client.md. Add instructions
for macOS; those are copied from the /apple endpoint and slightly
modified. Fix doc links in the README.
* Move infoboxes for /apple and /windows under the "Goal" section to the
top. Those should be seen by users first as they contain *their*
specific headscale URL.
* Swap order of macOS and iOS to move "Profiles" further down.
* Remove apple configuration profiles
* Remove Tailscale versions hints
* Mention /apple and /windows in the README along with their docs
See: #2096
* Simplify /windows to the bare minimum. Also remove the
/windows/tailscale.reg endpoint as its generated file is no longer
valid for current Tailscale versions.
* Update and simplify the windows documentation accordingly.
* Add a "Unattended mode" section to the troubleshooting section
explaining how to enable "Unattended mode" in the via the Tailscale
tray icon.
* Add infobox about /windows to the docs
Tested on Windows 10, 22H2 with Tailscale 1.72.0
Replaces: #1995
See: #2096