diff --git a/development/ref/api/index.html b/development/ref/api/index.html index 48f878228..ab883fa25 100644 --- a/development/ref/api/index.html +++ b/development/ref/api/index.html @@ -8,8 +8,8 @@
Headscale also serves a subset of the Tailscale-compatible API at /api/v2, which accepts OAuth 2.0 client-credentials in addition to API keys. The Tailscale client can use an OAuth client secret in place of an auth key: it exchanges the secret for an access token, mints a single-use tagged auth key and registers with it. This works anywhere the client takes an auth key: tailscale up, the container image, tsnet and the tailscale/github-action. One long-lived secret joins any number of nodes.
Create an OAuth client with the auth_keys scope and the tags its nodes get. The secret is shown once:
Build the auth key from the secret:
hskey-client-… becomes tskey-client-…. The client only runs the exchange for tskey-client-; Headscale accepts both.?baseURL=<your Headscale URL>.--advertise-tags. Each tag must exist in the policy's tagOwners and be one of the OAuth client's tags, or owned by one of them.Headscale also serves a subset of the Tailscale-compatible API at /api/v2, which accepts OAuth 2.0 client-credentials in addition to API keys. The Tailscale client can use an OAuth client secret in place of an auth key: it exchanges the secret for an access token, mints a single-use tagged auth key and registers with it. This works anywhere the client takes an auth key: tailscale up, the container image, tsnet and the tailscale/github-action. One long-lived secret joins any number of nodes. A client keeps its newest 1000 access tokens and minting more ends the oldest, so give a long-lived integration its own client.
Create an OAuth client with the auth_keys scope and the tags its nodes get. The secret is shown once:
Scopes apply to the whole tailnet, as in Tailscale: an auth_keys token can read and revoke auth keys of any tag, an oauth_keys token every OAuth client, and a devices:core:read token reads every device, routes included with fields=all. Keep the secret as safe as any credential that can revoke keys. Without all=true, a token lists only the auth keys made through a token, whatever their tags; with it, every valid auth key. No listing holds a spent, expired or revoked key. Tags limit only the tags a token puts on keys, clients and devices, and which tagged devices it may retag. Deleting an OAuth client revokes its secret and its access tokens; auth keys, clients and nodes created with it stay until you remove them.
Build the auth key from the secret:
hskey-client-… becomes tskey-client-…. The client only runs the exchange for tskey-client-; Headscale accepts both.?baseURL=<your Headscale URL>.--advertise-tags. Each tag must exist in the policy's tagOwners and be one of the OAuth client's tags, or owned by one of them.Warning
Without baseURL the client sends the secret to https://api.tailscale.com.
These are all the attributes the client understands; any other is an error. Order does not matter and an empty value means the default.
| Attribute | Default | Effect |
|---|---|---|
baseURL | https://api.tailscale.com | Where the exchange and key creation go. Your Headscale URL, no trailing slash. |
ephemeral | true | Node is removed after it goes offline (node.ephemeral.inactivity_timeout). false to keep it. |
preauthorized | false | Accepted, no effect: Headscale always authorizes pre-auth-key nodes. |
Booleans take any Go strconv.ParseBool value (true, false, 1, 0, …).
tailscale up, either as the auth key or via --client-secret (which also takes file:/path/to/secret):
tailscale up --login-server https://headscale.example.com --advertise-tags tag:ci \
--auth-key 'tskey-client-<id>-<secret>?baseURL=https://headscale.example.com&ephemeral=false'
Container image:
docker run -d --name tailscale \
diff --git a/development/ref/debug/index.html b/development/ref/debug/index.html
index 13e47ed1d..db7a4f951 100644
--- a/development/ref/debug/index.html
+++ b/development/ref/debug/index.html
@@ -8,7 +8,7 @@
log:
# Valid log levels: panic, fatal, error, warn, info, debug, trace
level: debug
-Headscale provides a metrics and debug endpoint. It allows to introspect different aspects such as:
Keep the metrics and debug endpoint private
The listen address and port can be configured with the metrics_listen_addr variable in the configuration file. By default it listens on localhost, port 9090.
Keep the metrics and debug endpoint private to your internal network and don't expose it to the Internet.
The metrics and debug interface can be disabled completely by setting metrics_listen_addr: null in the configuration file.
Query metrics via http://localhost:9090/metrics and get an overview of available debug information via http://localhost:9090/debug/. Metrics may be queried from outside localhost but the debug interface is subject to additional protection despite listening on all interfaces.
Access the debug interface directly on the server where Headscale is installed.
Headscale provides a metrics and debug endpoint. It allows to introspect different aspects such as:
Keep the metrics and debug endpoint private
The listen address and port can be configured with the metrics_listen_addr variable in the configuration file. By default it listens on localhost, port 9090.
Keep the metrics and debug endpoint private to your internal network and don't expose it to the Internet.
The metrics and debug interface can be disabled completely by setting metrics_listen_addr: null in the configuration file.
Query metrics via http://localhost:9090/metrics and get an overview of available debug information via http://localhost:9090/debug/. Metrics may be queried from outside localhost but the debug interface is subject to additional protection despite listening on all interfaces.
The debug interface accepts requests addressed to an IP literal, localhost, the host in server_url, or the hostname in metrics_listen_addr. Hostnames are case-insensitive and may end in a dot. Other hostnames receive HTTP 403; use an IP address or one of the accepted names. dns.base_domain does not add accepted hosts. This check covers all debug paths, including statsviz. /metrics accepts any Host.
Access the debug interface directly on the server where Headscale is installed.
Use SSH port forwarding to forward Headscale's metrics and debug port to your device.
Access the debug interface on your device by opening http://localhost:9090/debug/ in your web browser.
The access control of the debug interface supports the use of a debug key. Traffic is accepted if the path to a debug key is set via the environment variable TS_DEBUG_KEY_PATH and the debug key sent as value for debugkey parameter with each request.
openssl rand -hex 32 | tee debugkey.txt
export TS_DEBUG_KEY_PATH=debugkey.txt
diff --git a/development/ref/oidc/index.html b/development/ref/oidc/index.html
index 131a99036..0135aa531 100644
--- a/development/ref/oidc/index.html
+++ b/development/ref/oidc/index.html
@@ -28,7 +28,7 @@
scope: ["openid", "profile", "email", "groups"]
allowed_groups:
- "headscale_users"
-Headscale uses the email claim from the identity provider to synchronize the email address to its user profile. By default, a user's email address is only synchronized when the identity provider reports the email address as verified via the email_verified: true claim.
Unverified emails may be allowed in case an identity provider does not send the email_verified claim or email verification is not required. In that case, a user's email address is always synchronized to the user profile.
Headscale synchronizes the email claim from the identity provider to its user profile on each OIDC login. By default, the profile uses the email only when the latest login reports email_verified: true. An absent, unverified, or malformed email clears the previously stored address.
Unverified emails may be allowed in case an identity provider does not send the email_verified claim or email verification is not required. With email_verified_required: false, the latest login's email is stored without requiring verification. An absent or malformed email still clears the previously stored address.
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
@@ -41,7 +41,7 @@
client_secret: "generated-secret"
use_expiry_from_token: true
Expire a node and force re-authentication
A node can be expired immediately via:
You may refer to users in the Headscale policy via:
A user identifier in the policy must contain a single @
The Headscale policy requires a single @ to reference a user. If the username or provider identifier doesn't already contain a single @, it needs to be appended at the end. For example: the Headscale username ssmith has to be written as ssmith@ to be correctly identified as user within the policy.
Ensure that the Headscale username itself does not end with @.
Email address or username might be updated by users
Many identity providers allow users to update their own profile. Depending on the identity provider and its configuration, the values for username or email address might change over time. This might have unexpected consequences for Headscale where a policy might no longer work or a user might obtain more access by hijacking an existing username or email address.
Howto use the provider identifier in the policy
The provider identifier uniquely identifies an OIDC user and a well-behaving identity provider guarantees that this value never changes for a particular user. It is usually an opaque and long string and its value is currently only available from the API, database or directly from your identity provider).
Use the API with the /api/v1/user endpoint to fetch the provider identifier (providerId). The value (be sure to append an @ in case the provider identifier doesn't already contain an @ somewhere) can be used directly to reference a user in the policy. To improve readability of the policy, one may use the groups section as an alias:
You may refer to users in the Headscale policy via:
References match a provider identifier first, then a stored email address, then a username. A token shaped like an email address also matches a username with that value when no user has that email. If one user has the email and another has the username, the email owner wins. Multiple matching emails, or multiple matching usernames when no email matches, remain ambiguous.
A user identifier in the policy must contain a single @
The Headscale policy requires a single @ to reference a user. If the username or provider identifier doesn't already contain a single @, it needs to be appended at the end. For example: the Headscale username ssmith has to be written as ssmith@ to be correctly identified as user within the policy.
Ensure that the Headscale username itself does not end with @.
Email address or username might be updated by users
Many identity providers allow users to update their own profile. Depending on the identity provider and its configuration, the values for username or email address might change over time. This might have unexpected consequences for Headscale where a policy might no longer work or a user might obtain more access by hijacking an existing username or email address.
Use provider identifiers in policies when your identity provider lets users change their own usernames.
Howto use the provider identifier in the policy
The provider identifier uniquely identifies an OIDC user and a well-behaving identity provider guarantees that this value never changes for a particular user. It is usually an opaque and long string and its value is currently only available from the API, database or directly from your identity provider).
Use the API with the /api/v1/user endpoint to fetch the provider identifier (providerId). The value (be sure to append an @ in case the provider identifier doesn't already contain an @ somewhere) can be used directly to reference a user in the policy. To improve readability of the policy, one may use the groups section as an alias:
{
"groups": {
"group:alice": [
"https://sso.example.com/oauth2/openid/59ac9125-c31b-46c5-814e-06242908cf57@"
diff --git a/development/ref/routes/index.html b/development/ref/routes/index.html
index b41d58d2c..81bd3b76a 100644
--- a/development/ref/routes/index.html
+++ b/development/ref/routes/index.html
@@ -120,4 +120,4 @@
}
The Tailscale client can suggest a viable exit node with:
or automatically select one by using auto:any as exit node identifier:
Please see the official Tailscale documentation for more information on automatic exit node selection.
Headscale supports high availability routing. Multiple subnet routers with overlapping routes or multiple exit nodes can be used to provide high availability for users. If one router node goes offline, another one can serve the same routes to clients. Please see the official Tailscale documentation on high availability for details.
This feature is enabled by default when at least two nodes advertise the same prefix. See the configuration options node.routes.ha in the configuration file for details.
A subnet router or exit node is routing traffic on behalf of other nodes and thus requires IP forwarding. Check the official Tailscale documentation for how to enable IP forwarding.