Skip to content

v0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 14 Oct 10:03
· 11 commits to main since this release
5190550

Portal gateway mode: a person outside your tailnet accepts one device share, of the portal node, and you decide which apps they can use, on this host or on others, without sending more invitations. Gateway mode is opt-in; per-app sharing is unchanged and remains the default.

Upgrade

  • Homebrew: brew upgrade --cask anydoor7/tap/tslink. Scoop: scoop update; scoop update tslink. Other installs: download the new archive or package from this release.
  • If TSLink runs as a background service, run tslink install again after upgrading so the service starts the new binary.
  • Existing registries keep their schema version until gateway mode is configured; read Compatibility below before turning it on.

Added

  • tslink portal enable --gateway: a persistent portal node with one stable device identity, the private dashboard on port 443, and one HTTPS port per routed app (tslink portal route add|remove|list). Each connection is identified before TLS, each request is checked against people grants, and non-navigation requests from other origins, including other gateway ports, are refused unless a route opts out with --allow-cross-origin.
  • Portal-only apps (tslink add --portal-only) with no node of their own, and apps on other hosts (tslink add --remote https://<node>.<tailnet>.ts.net). Remote apps are reached only through the tagged gateway node's own netstack, using the peer address from the gateway's netmap, never through the host network or the host resolver. The remote host authenticates the gateway's tag; visitor identity is not forwarded.
  • One gateway device invite per person (tslink people add|update --invite); later grant changes need no new invite. An invite left behind by a gateway identity change is reported as stale and can be retired explicitly.
  • Periodic health checks for portal-only apps; gateway fields in status, list, url and doctor; access-log reason codes and connection-drop counts; MCP tools portal_route_add, portal_route_remove and portal_route_list, and gateway options for portal_enable and add.
  • tslink health set <app> and the owner MCP tool health_set change only an app's health check (path, status range, body, timeout, interval, or --reset) in one registry transaction, keeping access, tags, people scope, routes and the enrolled node. Use it instead of re-running add, which replaces the whole service.
  • App health reports the observed HTTP status_code. doctor reports a backend that answers outside its health settings as app_probe_unexpected_response (warning) with the exact tslink health set command to fix the check.
  • Access-log events for real backend failures add error_class (connection_refused, connection_reset, tls, timeout or other).

Changed

  • People-scoped apps now report allow.mode: people wherever an app's access summary is printed (list, status, add), including when gateway mode is off.
  • HTTP health checks without an explicit status range accept 200-399. Redirects are still not followed; a redirect proves the app answers. 401 and 403 need an explicit range. A single explicit bound keeps its previous meaning, and registries are not rewritten.
  • A health check that gets an unexpected status or body is degraded, never down, and sends no app_down alert. Only unreachable backends (refused, timed out, reset) become down after three consecutive failures.

Fixed

  • tslink invite list no longer fails when Tailscale returns an empty user-invite list as JSON null; device invitations stay visible. Device list completeness checks are unchanged.
  • Apps that redirect their root page, require authentication, or have no root route were reported down and triggered false app_down alerts, and the portal showed them as Down to visitors.
  • A client that cancels a request while TSLink identifies it, on an app node, a gateway route or the remote MCP control plane, is no longer recorded as an access denial or logged as an identification error, and the request is still never served. On app nodes and gateway routes, a client that cancels during proxying before the response starts is recorded as allowed with status 499 and client_canceled, instead of a 502 backend failure; once the response has started, the event keeps the status the client received. Requests that TSLink cancels itself, when it tears down a gateway route, when an app node's graceful shutdown runs out of time, or when a guest-gated app stops during a valid guest's request, are recorded as allowed with route_closed or node_closed, not as client cancellations, guest denials or backend failures: with status 503 before the response starts, and with the forwarded status once it has started. A guest grant that expires or is revoked during a request is still recorded as a denial.

Compatibility

Gateway configuration uses registry schema 3, which older releases refuse. Before downgrading, follow the steps in docs/portal.md: stop the daemon, back up the registry and portal state, remove portal-only and remote apps and all routes, and turn gateway mode off with this version. Recorded gateway invites keep the registry at schema 3 even with gateway mode off; if any remain, restore a registry backup taken before gateway mode was enabled (people and invite changes made since then are lost). Replacing only the binary is not a downgrade.