mirror of
https://github.com/tale/headplane.git
synced 2026-07-26 07:48:14 +00:00
feat: switch agent to a periodic dump rather than long running process
This commit is contained in:
+5
-6
@@ -1,6 +1,7 @@
|
||||
# Nix
|
||||
|
||||
[flake.nix](https://github.com/tale/headplane/blob/main/flake.nix) provided:
|
||||
|
||||
```sh
|
||||
$ nix flake show github:tale/headplane --all-systems
|
||||
github:tale/headplane/ec6d455461955242393b60d9ce60c5123fa9784f?narHash=sha256-CM/vXzUiOed7i1Pp15KyV4FuIvumRlXnpF33dSWZZH4%3D
|
||||
@@ -45,10 +46,12 @@ github:tale/headplane/ec6d455461955242393b60d9ce60c5123fa9784f?narHash=sha256-CM
|
||||
```
|
||||
|
||||
## NixOS module options
|
||||
|
||||
Defined as `services.headplane.*`, check the `./nix/` directory for details.\
|
||||
The full (generated by `mise run nixos-docs`) list of `services.headplane.settings.*` options: [./NixOS-options.md](./NixOS-options.md)
|
||||
|
||||
## Usage
|
||||
|
||||
1. Add the `github:tale/headplane` flake input.
|
||||
2. Import a default overlay to add `pkgs.headplane`.
|
||||
3. Import NixOS module for `services.headplane.*`.
|
||||
@@ -104,11 +107,11 @@ The full (generated by `mise run nixos-docs`) list of `services.headplane.settin
|
||||
headscale = {
|
||||
url = "https://example.com";
|
||||
config_path = "${headscaleConfig}";
|
||||
# Using `sops-nix` as an example, can be a path to any file with a secret.
|
||||
api_key_path = config.sops.secrets."headplane/headscaleApiKey".path;
|
||||
};
|
||||
integration.agent = {
|
||||
enabled = true;
|
||||
# Using `sops-nix` as an example, can be a path to any file with a secret.
|
||||
pre_authkey_path = config.sops.secrets."headplane/integrationAgentPreAuthkeyPath".path;
|
||||
};
|
||||
oidc = {
|
||||
issuer = "https://oidc.example.com";
|
||||
@@ -118,9 +121,6 @@ The full (generated by `mise run nixos-docs`) list of `services.headplane.settin
|
||||
disable_api_key_login = true;
|
||||
# Might needed when integrating with Authelia.
|
||||
token_endpoint_auth_method = "client_secret_basic";
|
||||
# Using `sops-nix` as an example, can be a path to any file with a secret.
|
||||
headscale_api_key_path = config.sops.secrets."headplane/oidcHeadscaleApiKey".path;
|
||||
redirect_uri = "https://oidc.example.com/admin/oidc/callback";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -131,4 +131,3 @@ The full (generated by `mise run nixos-docs`) list of `services.headplane.settin
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+33
-27
@@ -1,4 +1,5 @@
|
||||
# Configuration
|
||||
|
||||
> Previous versions of Headplane used environment variables without a configuration file.
|
||||
> Since 0.5, you will need to manually migrate your configuration to the new format.
|
||||
|
||||
@@ -12,8 +13,9 @@ This can be configured on a per-section basis in the configuration file, but
|
||||
it is very important this directory is persistent and writable by Headplane.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
It is also possible to override the configuration file using environment variables.
|
||||
These changes get merged *after* the configuration file is loaded, so they will take precedence.
|
||||
These changes get merged _after_ the configuration file is loaded, so they will take precedence.
|
||||
Environment variables follow this pattern: **`HEADPLANE_<SECTION>__<KEY_NAME>`**.
|
||||
For example, to override `oidc.client_secret`, you would set `HEADPLANE_OIDC__CLIENT_SECRET`
|
||||
to the value that you want.
|
||||
@@ -26,11 +28,13 @@ Here are a few more examples:
|
||||
**This functionality is NOT enabled by default!**
|
||||
To enable it, set the environment variable **`HEADPLANE_LOAD_ENV_OVERRIDES=true`**.
|
||||
Setting this also tells Headplane to load the relative `.env` file into the environment.
|
||||
|
||||
> Also note that this is **only** for configuration overrides, not for general
|
||||
> environment variables meaning you cannot specify variables such as
|
||||
> `HEADPLANE_DEBUG_LOG=true` or `HEADPLANE_CONFIG_PATH=/etc/headplane/config.yaml`.
|
||||
|
||||
## Sensitive Values
|
||||
|
||||
Headplane supports a dual-mode pattern for providing certain sensitive configuration values, such as secrets, keys, and private certificates. For each such field, you can either:
|
||||
|
||||
1. Set the value directly in the configuration file (e.g., `cookie_secret: "your-32-character-long-secret"`)
|
||||
@@ -39,6 +43,7 @@ Headplane supports a dual-mode pattern for providing certain sensitive configura
|
||||
When using a `_path` option, the content of the specified file will be read and used as the value for the setting. These paths can include environment variable interpolation (e.g., `${CREDENTIALS_DIRECTORY}/my_secret_file`), which is useful for integration with tools like systemd's `LoadCredential`.
|
||||
|
||||
**Important Rules for Dual-Mode Fields:**
|
||||
|
||||
- You **cannot** set both the direct value (e.g., `cookie_secret`) and its corresponding `_path` (e.g., `cookie_secret_path`) simultaneously. Doing so will result in a configuration error.
|
||||
- If a `_path` is provided, the corresponding direct value field (if also present and not null) will usually be ignored or may cause validation errors depending on the specific field and loader logic. It's best to provide only one.
|
||||
- The same dual-mode pattern works with environment variables. You can set `HEADPLANE_OIDC__CLIENT_SECRET` for a direct value or `HEADPLANE_OIDC__CLIENT_SECRET_PATH` to specify a path to a file containing the secret.
|
||||
@@ -50,39 +55,39 @@ The following configuration options in Headplane are treated as secret paths:
|
||||
|
||||
- **Server Settings (`server.*`):**
|
||||
- `cookie_secret_path` (for web session encoding)
|
||||
- *Note:* Either `cookie_secret` or `cookie_secret_path` must be provided for web session security.
|
||||
- _Note:_ Either `cookie_secret` or `cookie_secret_path` must be provided for web session security.
|
||||
|
||||
- **Headscale Connection Settings (`headscale.*`):**
|
||||
- `api_key_path` (Headscale API key for server-side operations like OIDC and agent sync)
|
||||
- _Note:_ Either `api_key` or `api_key_path` must be provided when using OIDC or the agent.
|
||||
- `tls_cert_path` (custom TLS certificate for connecting to Headscale)
|
||||
- *Note:* This is treated as a regular path, not a secret path, so it will not have its content loaded.
|
||||
|
||||
- **Integration Agent Settings (`integration.agent.*`):**
|
||||
- `pre_authkey_path` (pre-auth key for the Headplane agent to connect to the Tailnet)
|
||||
- *Note:* Either `pre_authkey` or `pre_authkey_path` must be provided when the agent is enabled.
|
||||
- _Note:_ This is treated as a regular path, not a secret path, so it will not have its content loaded.
|
||||
|
||||
- **OIDC Settings (`oidc.*`):**
|
||||
- `client_secret_path` (OIDC client secret)
|
||||
- *Note:* Either `client_secret` or `client_secret_path` must be provided for OIDC authentication.
|
||||
- `headscale_api_key_path` (Headscale API key used by Headplane during the OIDC authentication flow)
|
||||
- *Note:* Either `headscale_api_key` or `headscale_api_key_path` must be provided for OIDC integration.
|
||||
- _Note:_ Either `client_secret` or `client_secret_path` must be provided for OIDC authentication.
|
||||
- `headscale_api_key_path` (**deprecated**, use `headscale.api_key_path` instead)
|
||||
|
||||
**Distinction for Non-Secret Paths:**
|
||||
Other configuration fields that end with `_path` are treated as regular paths and will not have their content loaded. For example:
|
||||
- `server.agent.cache_path` (default: `/var/lib/headplane/agent_cache.json`): This is a direct file path where Headplane will *store* its agent cache data.
|
||||
|
||||
- `headscale.config_path`: This is an optional path to Headscale's `config.yaml` file, which Headplane might read or use for validation.
|
||||
|
||||
All path fields (both secret and non-secret) support environment variable interpolation using the `${VAR_NAME}` syntax.
|
||||
|
||||
The path-based secret loading mechanism also works with environment variables. For instance:
|
||||
|
||||
- `HEADPLANE_OIDC__CLIENT_SECRET_PATH=/path/to/secret/file` will load the OIDC client secret from the specified file
|
||||
- `HEADPLANE_SERVER__COOKIE_SECRET_PATH=${CREDENTIALS_DIRECTORY}/cookie_secret` will use environment variable interpolation in the path
|
||||
|
||||
## Debugging
|
||||
|
||||
To enable debug logging, set the **`HEADPLANE_DEBUG_LOG=true`** environment variable.
|
||||
This will enable all debug logs for Headplane, which could fill up log space very quickly.
|
||||
This is not recommended in production environments.
|
||||
|
||||
## Reverse Proxying
|
||||
|
||||
Reverse proxying is very common when deploying web applications. Headscale and
|
||||
Headplane are very similar in this regard. You can use the same configuration
|
||||
of any reverse proxy you are familiar with. Here is an example of how to do it
|
||||
@@ -97,44 +102,45 @@ using Traefik:
|
||||
http:
|
||||
routers:
|
||||
headscale:
|
||||
rule: 'Host(`headscale.tale.me`)'
|
||||
service: 'headscale'
|
||||
rule: "Host(`headscale.tale.me`)"
|
||||
service: "headscale"
|
||||
middlewares:
|
||||
- 'cors'
|
||||
- "cors"
|
||||
|
||||
rewrite:
|
||||
rule: 'Host(`headscale.tale.me`) && Path(`/`)'
|
||||
service: 'headscale'
|
||||
rule: "Host(`headscale.tale.me`) && Path(`/`)"
|
||||
service: "headscale"
|
||||
middlewares:
|
||||
- 'rewrite'
|
||||
- "rewrite"
|
||||
|
||||
headplane:
|
||||
rule: 'Host(`headscale.tale.me`) && PathPrefix(`/admin`)'
|
||||
service: 'headplane'
|
||||
rule: "Host(`headscale.tale.me`) && PathPrefix(`/admin`)"
|
||||
service: "headplane"
|
||||
|
||||
services:
|
||||
headscale:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: 'http://headscale:8080'
|
||||
- url: "http://headscale:8080"
|
||||
|
||||
headplane:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: 'http://headplane:3000'
|
||||
- url: "http://headplane:3000"
|
||||
|
||||
middlewares:
|
||||
rewrite:
|
||||
addPrefix:
|
||||
prefix: '/admin'
|
||||
prefix: "/admin"
|
||||
cors:
|
||||
headers:
|
||||
accessControlAllowHeaders: '*'
|
||||
accessControlAllowHeaders: "*"
|
||||
accessControlAllowMethods:
|
||||
- 'GET'
|
||||
- 'POST'
|
||||
- 'PUT'
|
||||
- "GET"
|
||||
- "POST"
|
||||
- "PUT"
|
||||
accessControlAllowOriginList:
|
||||
- 'https://headscale.tale.me'
|
||||
- "https://headscale.tale.me"
|
||||
accessControlMaxAge: 100
|
||||
addVaryHeader: true
|
||||
```
|
||||
|
||||
+23
-10
@@ -10,9 +10,21 @@ description: Configure the Headplane Agent for enhanced functionality.
|
||||
<figcaption>SSH access via the browser</figcaption>
|
||||
</figure>
|
||||
|
||||
The Headplane Agent is an optional component that can be enabled on your
|
||||
Headplane instance in order to unlock additional features such as remote
|
||||
web-based SSH and detailed machine information.
|
||||
The Headplane Agent is an optional component that periodically syncs node
|
||||
information (such as version and OS details) from the Tailnet. Unlike previous
|
||||
versions, the agent no longer runs as a persistent Tailnet node — it
|
||||
auto-generates pre-auth keys and performs periodic syncs instead.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before enabling the agent, ensure the following:
|
||||
|
||||
1. **Headscale 0.28 or newer** is required. The agent uses tag-only pre-auth
|
||||
keys which are only available in Headscale 0.28+.
|
||||
|
||||
2. **`headscale.api_key`** must be set in your Headplane configuration file.
|
||||
The agent uses this key to auto-generate ephemeral pre-auth keys for
|
||||
connecting to the Tailnet.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -22,15 +34,16 @@ please refer to the
|
||||
[example configuration](https://github.com/tale/headplane/blob/main/config.example.yaml)
|
||||
for details.
|
||||
|
||||
| Field | Description |
|
||||
|---------------------|--------------------------------------------------------|
|
||||
| **`integration.agent.enabled`** | Set to `true` to enable the agent. |
|
||||
| **`integration.agent.pre_authkey`** | A reusable pre-auth-key (see below). |
|
||||
| `integration.agent.host_name` | *Optional*. Host name to register as. |
|
||||
| `integration.agent.cache_path` | *Optional*. Cache path for the agent. |
|
||||
| `integration.agent.work_dir` | *Optional*. Working directory for the agent. |
|
||||
| Field | Description |
|
||||
| ----------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| **`integration.agent.enabled`** | Set to `true` to enable the agent. |
|
||||
| `integration.agent.host_name` | _Optional_. Headscale user name for the agent (default: `headplane-agent`). |
|
||||
| `integration.agent.cache_ttl` | _Optional_. How often to sync in milliseconds (default: `180000` / 3 minutes). |
|
||||
| `integration.agent.work_dir` | _Optional_. Working directory for the agent's tailnet state. |
|
||||
| `integration.agent.executable_path` | _Optional_. Path to the agent binary (default: `/usr/libexec/headplane/agent`). |
|
||||
|
||||
## Native Mode Configuration
|
||||
|
||||
Once you've built Headplane locally, there will be a binary in the `./build`
|
||||
folder called `hp_agent`. Please move this binary to
|
||||
`/usr/libexec/headplane/agent` and ensure that it is executable.
|
||||
|
||||
@@ -54,8 +54,11 @@ To enable OIDC authentication in Headplane, add the following to your
|
||||
configuration file:
|
||||
|
||||
```yaml
|
||||
headscale:
|
||||
url: "http://headscale:8080"
|
||||
api_key: "<generated-api-key>"
|
||||
|
||||
oidc:
|
||||
headscale_api_key: "<generated-api-key>"
|
||||
issuer: "https://your-idp.com"
|
||||
client_id: "your-client-id"
|
||||
client_secret: "your-client-secret"
|
||||
@@ -211,7 +214,7 @@ flow can be skipped. Once completed, users are taken to the main dashboard.
|
||||
setting. If Headplane is behind a reverse proxy with HTTPS, set it to `true`.
|
||||
If running without HTTPS (eg. local development), set it to `false`.
|
||||
|
||||
- **Invalid API Key**: The `oidc.headscale_api_key` may have expired. Generate
|
||||
- **Invalid API Key**: The `headscale.api_key` may have expired. Generate
|
||||
a new one with `headscale apikeys create --expiration 999d`.
|
||||
|
||||
- **Missing the `sub` claim**: Ensure your IdP includes the `sub` claim in the
|
||||
|
||||
Reference in New Issue
Block a user