docs: new installation docs!

This commit is contained in:
Aarnav Tale
2025-10-16 21:01:10 -04:00
parent 639e7e9c6b
commit 1b2d7e305a
15 changed files with 693 additions and 347 deletions
+266
View File
@@ -0,0 +1,266 @@
---
title: Docker
description: Install Headplane with Docker.
outline: [2, 3]
---
# Docker Installation
::: tip
If you are not looking to deploy with Docker, follow the
[**Native Mode**](./native-mode.md) deployment guide.
:::
The recommended way to deploy Headplane is through Docker. This method is quick,
easy, and works in most environments. It requires that Headscale is also running
with Docker.
## Prerequisites
- Docker and Docker Compose
- Headscale version 0.26.0 or later installed and running
- A [completed configuration file](/index.md#configuration) for Headplane.
## Installation
Running Headplane in with Docker is as simple as applying 1 compose file:
```yaml
services:
headplane:
image: ghcr.io/tale/headplane:latest
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './config.yaml:/etc/headplane/config.yaml'
- './headplane-data:/var/lib/headplane'
```
It's important to mount your configuration file and also provide a persistent
storage location for Headplane to store its own data. You can also change the
port mapping if you want to run it on a different port.
## Accessing Headplane
After starting the container, you can access the Headplane web interface by
navigating to `http://localhost:3000/admin` in your web browser (replace
`localhost` with your server's IP address or domain name if not running locally).
In order to log in, you'll need to supply a Headscale API key. You can create
one by running the following command within your Headscale environment:
```bash
# You may want to tweak the expiration duration as needed
headscale apikeys create --expiration 90d
```
## Enabling advanced features
You've technically completed the installation, but read on if you would like
to enable advanced features like the ability to edit network settings from the
UI or remote SSH from the browser.
### Network Management
Network management allows you to configure Tailnet settings such as DNS servers,
custom A records, the tailnet domain name, and MagicDNS from the Headplane UI.
#### Prerequisites
Network management (and other configurable Headscale features) requires that
Headplane and Headscale both run together in the same Docker machine. This is
because Headplane needs the following permissions:
- Access to read and write the Head**scale** configuration file through a shared
volume used by both Headscale and Headplane.
- Access to the Docker socket (usually `/var/run/docker.sock`, you may also use
a proxy such as [Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)).
#### Configuration
First you'll need to run both Headscale and Headplane in the same Docker
environment. Here is an example `compose.yaml` file that accomplishes this:
```yaml
services:
headplane:
image: ghcr.io/tale/headplane:latest
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
# Same as before
- '/path/to/your/config.yaml:/etc/headplane/config.yaml'
- '/path/to/data/storage:/var/lib/headplane'
# A shared path to the Headscale config file. It is important that the
# path you mount this on matches `headscale.config_path` in your
# Headplane config.yaml file.
- '/path/to/headscale/config.yaml:/etc/headscale/config.yaml'
# If you are using dns.extra_records in Headscale (recommended), you
# should also mount that file here so Headplane can read and write it.
# Ensure that the path matches `headscale.dns_records_path` in your
# Headplane config.yaml file.
- '/path/to/headscale/dns_records.json:/etc/headscale/dns_records.json'
# Read-only access to the Docker socket (or a proxy)
- '/var/run/docker.sock:/var/run/docker.sock:ro'
headscale:
image: headscale/headscale:0.26.0
container_name: headscale
restart: unless-stopped
command: serve
labels:
# This label is absolutely necessary to help Headplane find Headscale.
me.tale.headplane.target: headscale
ports:
- '8080:8080'
volumes:
# Notice how these are on the exact same path as the host for both
# Headscale and Headplane! This is very important.
- '/path/to/headscale/config.yaml:/etc/headscale/config.yaml'
- '/path/to/headscale/dns_records.json:/etc/headscale/dns_records.json'
- '/path/to/headscale/data/storage:/var/lib/headscale'
```
::: info
With some effort, you can technically run Headscale and Headplane in separate
Docker hosts and remotely connect to a Docker daemon. This is an advanced setup
that is not covered in this documentation. Refer to the
[example configuration](https://github.com/tale/headplane/blob/main/config.example.yaml)
for more details on setting it up.
:::
You'll also need to enable a few fields in your Headplane configuration file:
| Field | Description |
|---------------------|--------------------------------------------------------|
| **`integration.docker.enabled`** | Set to `true` to enable Docker integration. |
| **`headscale.config_path`** | Path to your Head**scale** configuration file within the container (e.g., `/etc/headscale/config.yaml`). |
| `headscale.dns_records_path` | *Optional*. Refer to the [example configuration](https://github.com/tale/headplane/blob/main/config.example.yaml) for details. |
With these settings in place, restart Headplane. You should now see additional
options in the UI navbar such as "DNS" and "Settings" where you can manage your
Tailnet configuration.
### Remote Web SSH
Remote Web SSH allows you to open a terminal session to your Tailscale nodes
directly from the Headplane web interface via
[Tailscale SSH](https://tailscale.com/kb/1193/tailscale-ssh). This feature
requires that Tailscale SSH is running on your nodes (done via
`tailscale up --ssh`).
This feature uses the [Headplane Agent](../features/agent.md) to facilitate the
SSH connections. Refer to the [Agent documentation](../features/agent.md) for
setup instructions.
### Single Sign-On (SSO)
Single Sign-On (SSO) authentication allows users to log in to Headplane using
external identity providers such as Google, GitHub, or any provider that
supports OpenID Connect (OIDC).
To get started with SSO, refer to the [SSO documentation](../features/sso.md)
for detailed setup instructions.
## Reverse Proxying
You *should* run Headplane behind a reverse proxy such as Nginx or Caddy in
production. Additionally, putting Headscale beind the reverse proxy allows
you to access both services via the same domain and TLS certificate.
#### Configuration
Headscale supports integrating with
[several reverse proxies](https://headscale.net/stable/ref/integration/reverse-proxy/)
such as Nginx, Caddy, Apache, etc. Deploying Headplane is as simple as adding
a handler to route any requests to `/admin` to the Headplane service. Refer
to the Traefik example below for a reference configuration. A similar setup via
Nginx without Docker is available in the
[Native Mode](./native-mode.md#reverse-proxying) installation documentation.
#### Example Traefik Configuration
The following configuration will set up Traefik to proxy all Headscale requests
on `headscale.example.com` and serve the Headplane UI under the `/admin` path.
This is identical to how Tailscale's own admin console is served.
Keep in mind this won't work on its own as you'll need to configure Traefik
and TLS certificates as needed. This is just a snippet to show how to configure
the routing for Headplane and Headscale.
<details>
<summary>Traefik config snippet</summary>
```yaml
services:
# Same as before
headplane:
image: ghcr.io/tale/headplane:latest
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- '/path/to/your/config.yaml:/etc/headplane/config.yaml'
- '/path/to/data/storage:/var/lib/headplane'
- '/path/to/headscale/config.yaml:/etc/headscale/config.yaml'
- '/path/to/headscale/dns_records.json:/etc/headscale/dns_records.json'
- '/var/run/docker.sock:/var/run/docker.sock:ro'
labels:
# Expose the admin UI at /admin
- 'traefik.enable=true'
- 'traefik.http.routers.headplane.rule=Host(`headscale.example.com`) && PathPrefix(`/admin`)'
- 'traefik.http.routers.headplane.entrypoints=websecure'
- 'traefik.http.routers.headplane.tls=true'
headscale:
image: headscale/headscale:0.26.0
container_name: headscale
restart: unless-stopped
command: serve
ports:
- '8080:8080'
volumes:
- '/path/to/headscale/config.yaml:/etc/headscale/config.yaml'
- '/path/to/headscale/dns_records.json:/etc/headscale/dns_records.json'
- '/path/to/headscale/data/storage:/var/lib/headscale'
labels:
- 'me.tale.headplane.target=headscale'
# Traefik labels to expose Headscale at headscale.example.com
- 'traefik.enable=true'
- 'traefik.http.routers.headscale.rule=Host(`headscale.example.com`)'
- 'traefik.http.routers.headscale.entrypoints=websecure'
- 'traefik.http.routers.headscale.tls=true'
# This middleware is essential to ensuring Headplane works correctly
- 'traefik.http.routers.headscale.middlewares=cors'
- 'traefik.http.middlewares.cors.headers.accesscontrolallowheaders=*'
- 'traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET,POST,PUT'
- 'traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=https://headscale.example.com'
- 'traefik.http.middlewares.cors.headers.accesscontrolmaxage=100'
- 'traefik.http.middlewares.cors.headers.addvaryheader=true'
# If you would optionally like to automatically redirect / to /admin
- 'traefik.http.routers.rewrite.rule=Host(`headscale.example.com`) && Path(`/`)'
- 'traefik.http.routers.rewrite.service=headscale'
- 'traefik.http.routers.rewrite.middlewares=rewrite'
- 'traefik.http.middlewares.rewrite.addprefix.prefix=/admin'
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- '80:80'
- '443:443'
volumes:
# Example volumes/setup, please configure Traefik as needed
- '/var/run/docker.sock:/var/run/docker.sock:ro'
- '/path/to/certs/storage:/certs'
```
</details>
+22
View File
@@ -0,0 +1,22 @@
---
title: Installation
description: Get started with Headplane.
---
# Installation
Headplane is designed to be deployed within several different environments to
ensure that it can seamlessly integrate into your existing infrastructure. First
set up your configuration file and then pick the installation method that best
suits your needs.
## Configuration
Headplane requires a configuration file to operate. A
[sample file](https://github.com/tale/headplane/blob/main/config.example.yaml)
is available to use as a starting point. Some of the important fields include:
| Field | Description |
|---------------------|--------------------------------------------------------|
| **`headscale.url`** | Point to your Headscale server (e.g., `http://headscale.example.com` or `http://headscale:8080` in Docker). |
| **`server.cookie_secret`** | Used to encrypt cookies. You can generate a random string using a command like `openssl rand -base64 32`. |
| **`server.data_path`** | Just a path to keep in mind, especially if you're using Docker. |
+86
View File
@@ -0,0 +1,86 @@
---
title: Limited Mode
description: Install Headplane in Limited Mode.
---
# Limited Mode
::: warning
**Limited Mode is not recommended for production use.**
Please consider using one of the other installation methods for a production
deployment. Limited mode lacks advanced features such as network management,
remote web SSH, and more.
:::
Limited Mode is good for users who want to test out the *basic* functionality
provided by Headplane. It only interacts with the Headplane API and lacks all
advanced features, making it suitable for local testing and development.
## Prerequisites
- Docker (and optionally Docker Compose)
- Headscale version 0.26.0 or later installed and running
- A [completed configuration file](/index.md#configuration) for Headplane.
## Installation
::: tip
If you want to test Limited Mode without Docker, you can follow the
[Native Mode](./native-mode.md) installation guide and simply avoid setting
up any of the advanced features.
:::
Running Headplane in Limited Mode is as simple as running 1 command:
```bash
docker run -d \
-p 3000:3000 \
-v /path/to/your/config.yaml:/etc/headplane/config.yaml \
-v /path/to/data/storage:/var/lib/headplane \
--name headplane
--restart unless-stopped
ghcr.io/tale/headplane:latest
```
It's important to mount your configuration file and also provide a persistent
storage location for Headplane to store its own data. You can also change the
port mapping if you want to run it on a different port.
<details>
<summary>Example Docker Compose configuration</summary>
```yaml
services:
headplane:
image: ghcr.io/tale/headplane:latest
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- '/path/to/your/config.yaml:/etc/headplane/config.yaml'
- '/path/to/data/storage:/var/lib/headplane'
```
</details>
## Accessing Headplane
After starting the container, you can access the Headplane web interface by
navigating to `http://localhost:3000/admin` in your web browser (replace
`localhost` with your server's IP address or domain name if not running locally).
In order to log in, you'll need to supply a Headscale API key. You can create
one by running the following command within your Headscale environment:
```bash
# You may want to tweak the expiration duration as needed
headscale apikeys create --expiration 90d
```
Limited Mode is intended for testing and development purposes, so please avoid
using it in a production environment. For production deployments, consider using
one of the other installation methods that will provide both the advanced
features of Headplane and a more robust deployment.
Limited Mode also technically supports
[Single Sign-On (SSO) authentication](../features/sso.md), but some parts of it
may not work as expected. For a full-featured experience with SSO, please use
one of the other installation methods.
+251
View File
@@ -0,0 +1,251 @@
---
title: Native Mode
description: Install Headplane without Docker.
outline: [2, 3]
---
# Native Mode
::: tip
If you are looking to deploy with Docker, follow the
[**Docker**](./docker.md) deployment guide.
:::
Headplane can be installed and run directly on your host system without the need
for Docker. This method is suitable for users who already run Headscale natively
or prefer to avoid containers.
## Prerequisites
- A Linux-based operating system (e.g, Ubuntu, Debian, CentOS, Fedora)
- Go version 1.25.1 installed (only needed to build Headplane)
- Node.js version 22.16.x and [pnpm](https://pnpm.io/) version 10.4.x installed
- Headscale version 0.26.0 or later installed and running
- A [completed configuration file](./index.md#configuration) for Headplane.
Before building and running Headplane, ensure that the directory defined in
`server.data_path` in your configuration exists and is writable by the user who
will run Headplane.
```bash
# Adjust as needed and set a custom user if you desire
sudo mkdir -p /var/lib/headplane
sudo chown -R $(whoami):$(whoami) /var/lib/headplane
```
## Building Headplane
Clone the Headplane repository, install dependencies, and build the project:
```bash
# You can optionally checkout a specific release tag.
git clone https://github.com/tale/headplane.git
cd headplane
pnpm install
pnpm build
```
## Running Headplane
Running Headplane is as straightforward as running `pnpm start` (or also
directly with `node build/server/index.js`). Headplane will look for a config
file at `/etc/headplane/config.yaml` by default, but you can specify a different
path by setting the `HEADPLANE_CONFIG_PATH` environment variable.
> Ensure that the `build/` directory exists relative to where the start command
> is run, otherwise Headplane will not be able to find the frontend assets.
<details>
<summary>Example Systemd service file</summary>
Slotting this file into `/etc/systemd/system/headplane.service` will allow
you to manage Headplane via systemd. Adjust the paths and user as needed,
run `sudo systemctl daemon-reload`, and then enable/start the service.
```ini
[Unit]
Description=Headplane Service
After=network.target # (or headscale.service if it runs via systemd)
Requires=network.target # (or headscale.service if it runs via systemd)
StartLimitIntervalSec=0
[Service]
Type=simple
User=your-username
WorkingDirectory=/path/to/your/cloned/headplane
ExecStart=/usr/bin/node /path/to/your/cloned/headplane/build/server/index.js
Restart=on-failure
RestartSec=5s
# Uncomment and set if using a custom config path
# Environment=HEADPLANE_CONFIG_PATH=/path/to/your/config.yaml
[Install]
WantedBy=multi-user.target
```
</details>
To access Headplane, navigate to `http://localhost:3000/admin` in your web
browser (replace `localhost` with your server's IP address or domain name if
not running locally).
In order to log in, you'll need to supply a Headscale API key. You can create
one by running the following command within your Headscale environment:
```bash
# You may want to tweak the expiration duration as needed
headscale apikeys create --expiration 90d
```
## Enabling advanced features
You've technically completed the installation, but read on if you would like
to enable advanced features like the ability to edit network settings from the
UI or remote SSH from the browser.
### Network Management
Network management allows you to configure Tailnet settings such as DNS servers,
custom A records, the tailnet domain name, and MagicDNS from the Headplane UI.
#### Prerequisites
Network management (and other configurable Headscale features) requires that
Headplane and Headscale both run on the same machine because Headplane needs
- Access to read and write the Head**scale** configuration file
- Access to read the `/proc` filesystem on Linux to locate Headscale's process
#### Configuration
Enabling network management is as simple as setting a few additional fields in
your Headplane configuration file:
| Field | Description |
|---------------------|--------------------------------------------------------|
| **`integration.proc.enabled`** | Set to `true` to enable process inspection. |
| **`headscale.config_path`** | Path to your Head**scale** configuration file (e.g., `/etc/headscale/config.yaml`). |
| `headscale.dns_records_path` | *Optional*. Refer to the [example configuration](https://github.com/tale/headplane/blob/main/config.example.yaml) for details. |
With these settings in place, restart Headplane. You should now see additional
options in the UI navbar such as "DNS" and "Settings" where you can manage your
Tailnet configuration.
### Remote Web SSH
Remote Web SSH allows you to open a terminal session to your Tailscale nodes
directly from the Headplane web interface via
[Tailscale SSH](https://tailscale.com/kb/1193/tailscale-ssh). This feature
requires that Tailscale SSH is running on your nodes (done via
`tailscale up --ssh`).
This feature uses the [Headplane Agent](../features/agent.md) to facilitate the
SSH connections. Refer to the [Agent documentation](../features/agent.md) for
setup instructions and specifically follow the
[native mode configuration](../features/agent.md#native-mode-configuration)
section to point Headplane to the correct agent location.
### Single Sign-On (SSO)
Single Sign-On (SSO) authentication allows users to log in to Headplane using
external identity providers such as Google, GitHub, or any provider that
supports OpenID Connect (OIDC).
To get started with SSO, refer to the [SSO documentation](../features/sso.md)
for detailed setup instructions.
## Reverse Proxying
You *should* run Headplane behind a reverse proxy such as Nginx or Caddy in
production. Additionally, putting Headscale beind the reverse proxy allows
you to access both services via the same domain and TLS certificate.
#### Configuration
::: tip
If you are using a [custom path prefix](#custom-path-prefix) for Headplane,
adjust the `/admin` paths in the examples below accordingly.
:::
Headscale supports integrating with
[several reverse proxies](https://headscale.net/stable/ref/integration/reverse-proxy/)
such as Nginx, Caddy, Apache, etc. Deploying Headplane is as simple as adding
a handler to route any requests to `/admin` to the Headplane service. Refer
to the Nginx example below for a reference configuration. A similar setup via
Traefik in Docker is available in the [Docker](./docker.md#reverse-proxying)
installation documentation.
#### Example Nginx Configuration
The following configuration will set up Nginx to proxy all Headscale requests
on `headscale.example.com` and serve the Headplane UI under the `/admin` path.
This is identical to how Tailscale's own admin console is served.
<details>
<summary>Nginx config snippet</summary>
```nginx
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name headscale.example.com;
# Or use LetsEncrypt with Certbot (up to you)
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / { # Headscale runs on the root path
proxy_pass http://localhost:8080/; # Adjust if Headscale runs on a different port
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
}
location /admin/ { # Headplane is served under /admin
proxy_pass http://localhost:3000/; # Adjust if Headplane runs on a different port
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
</details>
## Custom Path Prefix
::: warning
The only officially supported path prefix for Headplane is `/admin`. Using a
custom path prefix may lead to unexpected issues and is not recommended.
:::
If for whatever reason you do not want to serve Headplane under `/admin`
(e.g., you want to serve it under `/headplane`), you can set the prefix
while building Headplane via the `__INTERNAL_PREFIX` environment variable.
```bash
# Example for /headplane prefix
git clone
cd headplane
pnpm install
# Set the prefix here
__INTERNAL_PREFIX=/headplane pnpm build
```
When running Headplane, all requests will only be served under the specified
path. Make sure to also adjust your reverse proxy configuration accordingly if
you are using one. Additionally, if you want to change the path prefix again,
you will need to rebuild Headplane with the new prefix.