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
+1 -11
View File
@@ -32,17 +32,7 @@ These are some of the features that Headplane offers:
- Configurability for Headscale's settings
## Deployment
Headplane runs as a server-based web-application, meaning you'll need a server to run it.
It's available as a Docker image (recommended) or through a manual installation.
There are 2 ways to deploy Headplane:
- ### [Integrated Mode (Recommended)](/docs/Integrated-Mode.md)
Integrated mode unlocks all the features of Headplane and is the most
feature-complete deployment method. It communicates with Headscale directly.
- ### [Simple Mode](/docs/Simple-Mode.md)
Simple mode does not include the automatic management of DNS and Headplane
settings, requiring manual editing and reloading when making changes.
Refer to the [website](https://headplane.net) for detailed installation instructions.
## Versioning
Headplane uses [semantic versioning](https://semver.org/) for its releases (since v0.6.0).
+11 -6
View File
@@ -3,7 +3,6 @@ import { defineConfig } from 'vitepress';
export default defineConfig({
title: 'Headplane',
description: 'The missing dashboard for Headscale',
ignoreDeadLinks: ['/docs/Integrated-Mode', '/docs/Simple-Mode'],
cleanUrls: true,
head: [['link', { rel: 'icon', href: '/favicon.ico' }]],
themeConfig: {
@@ -11,13 +10,19 @@ export default defineConfig({
nav: [{ text: 'Home', link: '/' }],
sidebar: [
{
text: 'Chapters',
text: 'Getting Started',
items: [
{ text: 'Getting Started', link: '/README' },
{ text: 'What is Headplane?', link: '/introduction' },
{
text: 'Installation',
link: '/install',
items: [
{ text: 'Limited Mode', link: '/install/limited-mode' },
{ text: 'Native Mode', link: '/install/native-mode' },
{ text: 'Docker', link: '/install/docker' },
],
},
{ text: 'Configuration', link: '/Configuration' },
{ text: 'Bare-Metal Mode', link: '/Bare-Metal' },
{ text: 'Integrated Mode', link: '/Integrated-Mode' },
{ text: 'Simple Mode', link: '/Simple-Mode' },
{ text: 'Nix', link: '/Nix' },
{ text: 'NixOS', link: '/NixOS-options' },
{ text: 'Security', link: '/SECURITY' },
-92
View File
@@ -1,92 +0,0 @@
# Bare-Metal Mode
Bare-Metal mode is the most flexible way to deploy Headplane. It allows you to
run Headplane on any system without the need for Docker or any other container
runtime. This is not recommended, but I understand that everyone has
different needs.
> It works with both the **Simple** and **Integrated** deployment modes. Refer
> to the section below for instructions on configuring Integrated mode.
## Deployment
Requirements:
- Headscale 0.26 or newer (already deployed)
- Node.js **22.16** LTS or newer
- [PNPM](https://pnpm.io/installation) 10.x
- A finished configuration file (config.yaml)
Before installing Headplane, ensure that `/var/lib/headplane` exists and is
writable by the user that will run the Headplane service. You can create this
directory with the following command:
```sh
sudo mkdir -p /var/lib/headplane
# Replace headplane:headplane with the appropriate user and group if not root.
sudo chown -R headplane:headplane /var/lib/headplane
```
Clone the Headplane repository, install dependencies, and build the project:
```sh
git clone https://github.com/tale/headplane
cd headplane
git checkout v0.6.0 # Or whatever tag you want to use
pnpm install
pnpm build
```
## Running Headplane
You can start headplane through `pnpm start` or `node build/headplane/server.js`.
Headplane expects the `build` directory to be present when running the server.
The structure of this folder is very important and should not be tampered with.
### Integrated Mode
Since you are running Headplane in Bare-Metal, you most likely also are running
Headscale in Bare-Metal. Refer to the [**Integrated Mode**](./Integrated-Mode.md)
guide for instructions on setting up the integrated mode in Native Linux (/proc).
### Changing the Admin Path
Since you are building Headplane yourself, you are able to configure the admin
path to be anything you want. When running `pnpm build`, you can pass the
`__INTERNAL_PREFIX` environment variable to change the admin path. For example:
```sh
__INTERNAL_PREFIX=/admin2 pnpm build
```
Just keep in mind that the admin path is not configurable at runtime, so you
will need to rebuild the project if you want to change it. Also, anything aside
from `/admin` is not officially supported and could break in future versions.
> Refer to the [**Configuration**](./Configuration.md) guide for help with
> setting up your `config.yaml` file to the appropriate values.
### Systemd Unit
Here is an example of a systemd unit file that you can use to manage the
Headplane service:
```ini
[Unit]
Description=Headplane
# Decomment the following line if running on bare metal with integrated mode (/proc integration)
# PartOf=headscale.service
[Service]
Type=simple
User=headplane
Group=headplane
WorkingDirectory=/path/to/headplane
ExecStart=/usr/bin/node /path/to/headplane/build/server/index.js
Restart=always
[Install]
WantedBy=multi-user.target
```
You will need to replace `/path/to/headplane` with the actual path to the
Headplane repository on your system. Save this file as `headplane.service` in
`/etc/systemd/system/` and run `systemctl enable headplane` to enable the service.
Other fields may also need some configuration, as this unit expects a user and a
group called `headplane` to exist on the system. You can change these values to
match your system's configuration.
-199
View File
@@ -1,199 +0,0 @@
# Integrated Mode
<picture>
<source
media="(prefers-color-scheme: dark)"
srcset="./assets/dns-dark.png"
>
<source
media="(prefers-color-scheme: light)"
srcset="./assets/dns-light.png"
>
<img
alt="Integration Preview"
src="./assets/dns-dark.png"
>
</picture>
Integrated mode is a deployment method that allows you to deploy Headplane with
automatic management of DNS and Headplane settings. This is the recommended
deployment method for most users, as it provides a more feature-complete
experience.
## Deployment
> If you are not looking to deploy with Docker, follow the [**Bare-Metal**](./Bare-Metal.md) deployment guide.
> Refer to the `Integrated Mode` section at the bottom for caveats.
Requirements:
- Docker and Docker Compose
- Headscale 0.26 or newer
- A finished configuration file (config.yaml)
Here is what a sample Docker Compose deployment would look like:
```yaml
services:
headplane:
# I recommend you pin the version to a specific release
image: ghcr.io/tale/headplane:0.6.0
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './config.yaml:/etc/headplane/config.yaml'
# This should match headscale.config_path in your config.yaml
- './headscale-config/config.yaml:/etc/headscale/config.yaml'
# If using dns.extra_records in Headscale (recommended), this should
# match the headscale.dns_records_path in your config.yaml
- './headscale-config/dns_records.json:/etc/headscale/dns_records.json'
# Headplane stores its data in this directory
- './headplane-data:/var/lib/headplane'
# If you are using the Docker integration, mount the Docker socket
- '/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 is needed for Headplane to find it and signal it
me.tale.headplane.target: headscale
ports:
- '8080:8080'
volumes:
- './headscale-data:/var/lib/headscale'
- './headscale-config:/etc/headscale'
```
This will result in the Headplane UI being available at the `/admin` path of the
server you deployed it on. The `/admin` path is currently not configurable unless
you build the container yourself or run Headplane in Bare-Metal mode.
> Refer to the [**Configuration**](./Configuration.md) guide for help with
> setting up your `config.yaml` file to the appropriate values.
## Docker Integration
The Docker integration is the easiest to set up, as it only requires mounting the
Docker socket into the container along with some basic configuration. Headplane
uses Docker labels to discover the Headscale container. As long as Headplane has
access to the Docker socket and can identify the Headscale container—either by
label or name—it will automatically propagate configuration and DNS changes to
Headscale without any additional setup. Alternatively, instead of using a label
to dynamically determine the container name, it is possible to directly specify
the container name.
## Native Linux (/proc) Integration
The `proc` integration is used when you are running Headscale and Headplane on
non-Docker environments. Headplane will attempt to locate the Headscale process
PID through the `/proc` filesystem and communicate with it directly. In order for
this to work, the Headplane process must have permission to do the following:
- Read the `/proc` filesystem
- Send signals to the Headscale process (`SIGTERM`)
The best way to ensure this is to run Headplane as the same user as Headscale
(or optionally just run them both as `root`). Due to the way the integration is
currently configured, Headplane will not re-check the Headscale process PID if
it changes. This means that if you restart Headscale manually, you will need to
restart Headplane as well.
## Kubernetes Integration
The Kubernetes integration is the most complex to setup, as it requires a
service account with the appropriate permissions to be created. The service
account must have the following permissions and looks like this:
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: headplane-agent
namespace: default # Adjust namespace as needed
rules:
- apiGroups: ['']
resources: ['pods']
verbs: ['get', 'list']
- apiGroups: ['apps']
resources: ['deployments']
verbs: ['get', 'list']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: headplane-agent
namespace: default # Adjust namespace as needed
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: headplane-agent
subjects:
- kind: ServiceAccount
name: default # If you use a different service account, change this
namespace: default # Adjust namespace as needed
```
To successfully deploy Headplane in Kubernetes, you will need to run both the
Headplane and Headscale containers in the same pod. This is because Headplane
needs access to Headscale's PID in order to communicate with it. Here is an
example, note the **`shareProcessNamespace: true`** field:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: headplane
namespace: default # Adjust namespace as needed
labels:
app: headplane
spec:
replicas: 1
selector:
matchLabels:
app: headplane
template:
metadata:
labels:
app: headplane
spec:
shareProcessNamespace: true
serviceAccountName: default
containers:
- name: headplane
image: ghcr.io/tale/headplane:0.6.0
env:
# Set these if the pod name for Headscale is not static
# We will use the downward API to get the pod name instead
- name: HEADPLANE_LOAD_ENV_OVERRIDES
value: 'true'
- name: 'HEADPLANE_INTEGRATION__KUBERNETES__POD_NAME'
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: headscale-config
mountPath: /etc/headscale
- name: headplane-data
mountPath: /var/lib/headplane
- name: headscale
image: headscale/headscale:0.26.0
command: ['serve']
volumeMounts:
- name: headscale-data
mountPath: /var/lib/headscale
- name: headscale-config
mountPath: /etc/headscale
volumes:
- name: headscale-data
persistentVolumeClaim:
claimName: headscale-data
- name: headplane-data
persistentVolumeClaim:
claimName: headplane-data
- name: headscale-config
persistentVolumeClaim:
claimName: headscale-config
```
-1
View File
@@ -1 +0,0 @@
./../README.md
-37
View File
@@ -1,37 +0,0 @@
# Simple Mode
Simple mode enables you to quickly deploy Headplane and is recommended for any
testing or simple environments. It does not include the automatic management of
DNS and Headplane settings, requiring manual editing and reloading when making
changes. If you're looking for a more feature-complete deployment method, check
out [**Integrated Mode**](./Integrated-Mode.md).
## Deployment
> If you are not looking to deploy with Docker, follow the [**Bare-Metal**](./Bare-Metal.md) deployment guide.
Requirements:
- Docker and Docker Compose
- Headscale 0.26 or newer (already deployed)
- A finished configuration file (config.yaml)
Here is what a sample Docker Compose deployment would look like:
```yaml
services:
headplane:
# I recommend you pin the version to a specific release
image: ghcr.io/tale/headplane:0.6.0
container_name: headplane
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- './config.yaml:/etc/headplane/config.yaml'
- './headplane-data:/var/lib/headplane'
```
This will result in the Headplane UI being available at the `/admin` path of the
server you deployed it on. The `/admin` path is currently not configurable unless
you build the container yourself or run Headplane in Bare-Metal mode.
> Refer to the [**Configuration**](./Configuration.md) guide for help with
> setting up your `config.yaml` file to the appropriate values.
+7
View File
@@ -0,0 +1,7 @@
---
title: Headplane Agent
description: Configure the Headplane Agent for enhanced functionality.
---
# Headplane Agent
TODO
+7
View File
@@ -0,0 +1,7 @@
---
title: Single Sign-On (SSO)
description: Configure Single Sign-On (SSO) authentication for Headplane.
---
# Single Sign-On (SSO)
TODO
View File
+4 -1
View File
@@ -10,7 +10,10 @@ hero:
alt: "Headplane"
actions:
- text: "Getting Started"
link: "/README"
link: "/introduction"
- text: "Installation"
link: "/install"
theme: "alt"
- text: "GitHub"
link: "https://github.com/tale/headplane"
theme: "alt"
+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.
+38
View File
@@ -0,0 +1,38 @@
---
title: Introduction
description: What is Headplane?
---
# What is Headplane (and Headscale)?
Headplane is a web-based UI that bridges the transforms Headscale into a
feature-rich VPN platform that rivals Tailscale's official offering. Headscale
is a self-hosted implementation of the Tailscale control server, enabling users
to create and manage their own private VPN networks via the Tailscale client.
<img class="dark-only" src="./assets/preview-dark.png" />
<img class="light-only" src="./assets/preview-light.png" />
Headscale does not ship with any web UI by default, which is where Headplane
comes in. Headplane provides a comprehensive web interface for managing your
Headscale instance, allowing you to easily administer your nodes, networks, and
ACLs.
It goes beyond basic management features, offering advanced capabilities such as
remote web-based SSH access to your nodes, single sign-on (SSO) via OpenID
Connect (OIDC), and detailed insights into your Tailnet's configuration and
status. Things like DNS management, ACL editing, and Headscale configuration can
all be done directly from the Headplane UI when compared to other Headscale UIs.
<img class="dark-only" src="./assets/dns-dark.png" />
<img class="light-only" src="./assets/dns-light.png" />
Headplane aims to replicate the functionality offered by the official Tailscale
product and dashboard, being one of the most feature complete Headscale UIs available.
These are some of the features that Headplane offers:
- Machine management, including expiry, network routing, name, and owner management
- Access Control List (ACL) and tagging configuration for ACL enforcement
- Support for OpenID Connect (OIDC) as a login provider
- The ability to edit DNS settings and automatically provision Headscale
- Configurability for Headscale's settings