mirror of
https://github.com/tale/headplane.git
synced 2026-08-27 23:47:31 +00:00
docs: new installation docs!
This commit is contained in:
@@ -32,17 +32,7 @@ These are some of the features that Headplane offers:
|
|||||||
- Configurability for Headscale's settings
|
- Configurability for Headscale's settings
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
Headplane runs as a server-based web-application, meaning you'll need a server to run it.
|
Refer to the [website](https://headplane.net) for detailed installation instructions.
|
||||||
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.
|
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
Headplane uses [semantic versioning](https://semver.org/) for its releases (since v0.6.0).
|
Headplane uses [semantic versioning](https://semver.org/) for its releases (since v0.6.0).
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { defineConfig } from 'vitepress';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
title: 'Headplane',
|
title: 'Headplane',
|
||||||
description: 'The missing dashboard for Headscale',
|
description: 'The missing dashboard for Headscale',
|
||||||
ignoreDeadLinks: ['/docs/Integrated-Mode', '/docs/Simple-Mode'],
|
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
head: [['link', { rel: 'icon', href: '/favicon.ico' }]],
|
head: [['link', { rel: 'icon', href: '/favicon.ico' }]],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
@@ -11,13 +10,19 @@ export default defineConfig({
|
|||||||
nav: [{ text: 'Home', link: '/' }],
|
nav: [{ text: 'Home', link: '/' }],
|
||||||
sidebar: [
|
sidebar: [
|
||||||
{
|
{
|
||||||
text: 'Chapters',
|
text: 'Getting Started',
|
||||||
items: [
|
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: '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: 'Nix', link: '/Nix' },
|
||||||
{ text: 'NixOS', link: '/NixOS-options' },
|
{ text: 'NixOS', link: '/NixOS-options' },
|
||||||
{ text: 'Security', link: '/SECURITY' },
|
{ text: 'Security', link: '/SECURITY' },
|
||||||
|
|||||||
@@ -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.
|
|
||||||
@@ -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 +0,0 @@
|
|||||||
./../README.md
|
|
||||||
@@ -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.
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Headplane Agent
|
||||||
|
description: Configure the Headplane Agent for enhanced functionality.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Headplane Agent
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Single Sign-On (SSO)
|
||||||
|
description: Configure Single Sign-On (SSO) authentication for Headplane.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Single Sign-On (SSO)
|
||||||
|
TODO
|
||||||
+4
-1
@@ -10,7 +10,10 @@ hero:
|
|||||||
alt: "Headplane"
|
alt: "Headplane"
|
||||||
actions:
|
actions:
|
||||||
- text: "Getting Started"
|
- text: "Getting Started"
|
||||||
link: "/README"
|
link: "/introduction"
|
||||||
|
- text: "Installation"
|
||||||
|
link: "/install"
|
||||||
|
theme: "alt"
|
||||||
- text: "GitHub"
|
- text: "GitHub"
|
||||||
link: "https://github.com/tale/headplane"
|
link: "https://github.com/tale/headplane"
|
||||||
theme: "alt"
|
theme: "alt"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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. |
|
||||||
@@ -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.
|
||||||
|
|
||||||
@@ -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.
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user