From 249630bed8001e3ec634b8c3578ba6d6308616d3 Mon Sep 17 00:00:00 2001 From: Florian Preinstorfer Date: Sun, 26 Oct 2025 09:12:53 +0100 Subject: [PATCH] Add API documentation Document the API endpoint and the built-in swagger docs at /swagger. The remote control docs are just a use case for gRPC - move it in the API docs and update links to it. --- .prettierignore | 2 +- CHANGELOG.md | 2 +- docs/about/faq.md | 2 +- docs/ref/api.md | 128 +++++++++++++++++++++++++++++++++++++ docs/ref/remote-cli.md | 99 ---------------------------- docs/setup/requirements.md | 2 +- mkdocs.yml | 7 +- 7 files changed, 136 insertions(+), 106 deletions(-) create mode 100644 docs/ref/api.md delete mode 100644 docs/ref/remote-cli.md diff --git a/.prettierignore b/.prettierignore index 4452a8a6..ebb727cc 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,5 @@ .github/workflows/test-integration-v2* docs/about/features.md +docs/ref/api.md docs/ref/configuration.md docs/ref/oidc.md -docs/ref/remote-cli.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 671156e5..4c598988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -995,7 +995,7 @@ behaviour. - Add IPv6 support to the prefix assigned to namespaces - Add API Key support - Enable remote control of `headscale` via CLI - [docs](./docs/ref/remote-cli.md) + [docs](./docs/ref/api.md#grpc) - Enable HTTP API (beta, subject to change) - OpenID Connect users will be mapped per namespaces - Each user will get its own namespace, created if it does not exist diff --git a/docs/about/faq.md b/docs/about/faq.md index ecedf198..f1361590 100644 --- a/docs/about/faq.md +++ b/docs/about/faq.md @@ -157,7 +157,7 @@ indicates which part of the policy is invalid. Follow these steps to fix your po !!! warning "Full server configuration required" The above commands to get/set the policy require a complete server configuration file including database settings. A - minimal config to [control Headscale via remote CLI](../ref/remote-cli.md) is not sufficient. You may use `headscale + minimal config to [control Headscale via remote CLI](../ref/api.md#grpc) is not sufficient. You may use `headscale -c /path/to/config.yaml` to specify the path to an alternative configuration file. ## How can I avoid to send logs to Tailscale Inc? diff --git a/docs/ref/api.md b/docs/ref/api.md new file mode 100644 index 00000000..44f87799 --- /dev/null +++ b/docs/ref/api.md @@ -0,0 +1,128 @@ +# API +Headscale provides a [HTTP REST API](#rest-api) and a [gRPC interface](#grpc) which may be used to integrate a [web +interface](integration/web-ui.md), [remote control Headscale](#setup-remote-control) or provide a base for custom +integration and tooling. + +Both interfaces require a valid API key before use. To create an API key, log into your Headscale server and generate +one with the default expiration of 90 days: + +```shell +headscale apikeys create +``` + +Copy the output of the command and save it for later. Please note that you can not retrieve an API key again. If the API +key is lost, expire the old one, and create a new one. + +To list the API keys currently associated with the server: + +```shell +headscale apikeys list +``` + +and to expire an API key: + +```shell +headscale apikeys expire --prefix +``` + +## REST API + +- API endpoint: `/api/v1`, e.g. `https://headscale.example.com/api/v1` +- Documentation: `/swagger`, e.g. `https://headscale.example.com/swagger` +- Authenticate using HTTP Bearer authentication by sending the [API key](#api) with the HTTP `Authorization: Bearer + ` header. + +Start by [creating an API key](#api) and test it with the examples below. Read the API documentation provided by your +Headscale server at `/swagger` for details. + +=== "Get details for all users" + + ```console + curl -H "Authorization: Bearer " \ + https://headscale.example.com/api/v1/user + ``` + +=== "Get details for user 'bob'" + + ```console + curl -H "Authorization: Bearer " \ + https://headscale.example.com/api/v1/user?name=bob + ``` + +=== "Register a node" + + ```console + curl -H "Authorization: Bearer " \ + -d user= -d key= \ + https://headscale.example.com/api/v1/node/register + ``` + +## gRPC + +The gRPC interface can be used to control a Headscale instance from a remote machine with the `headscale` binary. + +### Prerequisite + +- A workstation to run `headscale` (any supported platform, e.g. Linux). +- A Headscale server with gRPC enabled. +- Connections to the gRPC port (default: `50443`) are allowed. +- Remote access requires an encrypted connection via TLS. +- An [API key](#api) to authenticate with the Headscale server. + +### Setup remote control + +1. Download the [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases). Make + sure to use the same version as on the server. + +1. Put the binary somewhere in your `PATH`, e.g. `/usr/local/bin/headscale` + +1. Make `headscale` executable: `chmod +x /usr/local/bin/headscale` + +1. [Create an API key](#api) on the Headscale server. + +1. Provide the connection parameters for the remote Headscale server either via a minimal YAML configuration file or + via environment variables: + + === "Minimal YAML configuration file" + + ```yaml title="config.yaml" + cli: + address: : + api_key: + ``` + + === "Environment variables" + + ```shell + export HEADSCALE_CLI_ADDRESS=":" + export HEADSCALE_CLI_API_KEY="" + ``` + + This instructs the `headscale` binary to connect to a remote instance at `:`, instead of + connecting to the local instance. + +1. Test the connection by listing all nodes: + + ```shell + headscale nodes list + ``` + + You should now be able to see a list of your nodes from your workstation, and you can + now control the Headscale server from your workstation. + +### Behind a proxy + +It's possible to run the gRPC remote endpoint behind a reverse proxy, like Nginx, and have it run on the _same_ port as Headscale. + +While this is _not a supported_ feature, an example on how this can be set up on +[NixOS is shown here](https://github.com/kradalby/dotfiles/blob/4489cdbb19cddfbfae82cd70448a38fde5a76711/machines/headscale.oracldn/headscale.nix#L61-L91). + +### Troubleshooting + +- Make sure you have the _same_ Headscale version on your server and workstation. +- Ensure that connections to the gRPC port are allowed. +- Verify that your TLS certificate is valid and trusted. +- If you don't have access to a trusted certificate (e.g. from Let's Encrypt), either: + - Add your self-signed certificate to the trust store of your OS _or_ + - Disable certificate verification by either setting `cli.insecure: true` in the configuration file or by setting + `HEADSCALE_CLI_INSECURE=1` via an environment variable. We do **not** recommend to disable certificate validation. diff --git a/docs/ref/remote-cli.md b/docs/ref/remote-cli.md deleted file mode 100644 index 61df67fd..00000000 --- a/docs/ref/remote-cli.md +++ /dev/null @@ -1,99 +0,0 @@ -# Controlling headscale with remote CLI - -This documentation has the goal of showing a user how-to control a headscale instance -from a remote machine with the `headscale` command line binary. - -## Prerequisite - -- A workstation to run `headscale` (any supported platform, e.g. Linux). -- A headscale server with gRPC enabled. -- Connections to the gRPC port (default: `50443`) are allowed. -- Remote access requires an encrypted connection via TLS. -- An API key to authenticate with the headscale server. - -## Create an API key - -We need to create an API key to authenticate with the remote headscale server when using it from our workstation. - -To create an API key, log into your headscale server and generate a key: - -```shell -headscale apikeys create --expiration 90d -``` - -Copy the output of the command and save it for later. Please note that you can not retrieve a key again, -if the key is lost, expire the old one, and create a new key. - -To list the keys currently associated with the server: - -```shell -headscale apikeys list -``` - -and to expire a key: - -```shell -headscale apikeys expire --prefix "" -``` - -## Download and configure headscale - -1. Download the [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases). Make - sure to use the same version as on the server. - -1. Put the binary somewhere in your `PATH`, e.g. `/usr/local/bin/headscale` - -1. Make `headscale` executable: - - ```shell - chmod +x /usr/local/bin/headscale - ``` - -1. Provide the connection parameters for the remote headscale server either via a minimal YAML configuration file or via - environment variables: - - === "Minimal YAML configuration file" - - ```yaml title="config.yaml" - cli: - address: : - api_key: - ``` - - === "Environment variables" - - ```shell - export HEADSCALE_CLI_ADDRESS=":" - export HEADSCALE_CLI_API_KEY="" - ``` - - This instructs the `headscale` binary to connect to a remote instance at `:`, instead of - connecting to the local instance. - -1. Test the connection - - Let us run the headscale command to verify that we can connect by listing our nodes: - - ```shell - headscale nodes list - ``` - - You should now be able to see a list of your nodes from your workstation, and you can - now control the headscale server from your workstation. - -## Behind a proxy - -It is possible to run the gRPC remote endpoint behind a reverse proxy, like Nginx, and have it run on the _same_ port as headscale. - -While this is _not a supported_ feature, an example on how this can be set up on -[NixOS is shown here](https://github.com/kradalby/dotfiles/blob/4489cdbb19cddfbfae82cd70448a38fde5a76711/machines/headscale.oracldn/headscale.nix#L61-L91). - -## Troubleshooting - -- Make sure you have the _same_ headscale version on your server and workstation. -- Ensure that connections to the gRPC port are allowed. -- Verify that your TLS certificate is valid and trusted. -- If you don't have access to a trusted certificate (e.g. from Let's Encrypt), either: - - Add your self-signed certificate to the trust store of your OS _or_ - - Disable certificate verification by either setting `cli.insecure: true` in the configuration file or by setting - `HEADSCALE_CLI_INSECURE=1` via an environment variable. We do **not** recommend to disable certificate validation. diff --git a/docs/setup/requirements.md b/docs/setup/requirements.md index 627e24ed..ae1ea660 100644 --- a/docs/setup/requirements.md +++ b/docs/setup/requirements.md @@ -28,7 +28,7 @@ The ports in use vary with the intended scenario and enabled features. Some of t - STUN, required if the [embedded DERP server](../ref/derp.md) is enabled - tcp/50443 - Expose publicly: yes - - Only required if the gRPC interface is used to [remote-control Headscale](../ref/remote-cli.md). + - Only required if the gRPC interface is used to [remote-control Headscale](../ref/api.md#grpc). - tcp/9090 - Expose publicly: no - [Metrics and debug endpoint](../ref/debug.md#metrics-and-debug-endpoint) diff --git a/mkdocs.yml b/mkdocs.yml index 45634ece..a55f45f7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,11 +77,12 @@ plugins: apple-client.md: usage/connect/apple.md dns-records.md: ref/dns.md exit-node.md: ref/routes.md - ref/exit-node.md: ref/routes.md faq.md: about/faq.md iOS-client.md: usage/connect/apple.md#ios oidc.md: ref/oidc.md - remote-cli.md: ref/remote-cli.md + ref/exit-node.md: ref/routes.md + ref/remote-cli.md: ref/api.md#grpc + remote-cli.md: ref/api.md#grpc reverse-proxy.md: ref/integration/reverse-proxy.md tls.md: ref/tls.md web-ui.md: ref/integration/web-ui.md @@ -182,7 +183,7 @@ nav: - ACLs: ref/acls.md - DNS: ref/dns.md - DERP: ref/derp.md - - Remote CLI: ref/remote-cli.md + - API: ref/api.md - Debug: ref/debug.md - Integration: - Reverse proxy: ref/integration/reverse-proxy.md