From 1b2d7e305afe4920543900331e59f905a61ca32d Mon Sep 17 00:00:00 2001 From: Aarnav Tale Date: Thu, 16 Oct 2025 21:01:10 -0400 Subject: [PATCH] docs: new installation docs! --- README.md | 12 +- docs/.vitepress/config.ts | 17 ++- docs/Bare-Metal.md | 92 ------------ docs/Integrated-Mode.md | 199 -------------------------- docs/README.md | 1 - docs/Simple-Mode.md | 37 ----- docs/features/agent.md | 7 + docs/features/sso.md | 7 + docs/getting-started.md | 0 docs/index.md | 5 +- docs/install/docker.md | 266 +++++++++++++++++++++++++++++++++++ docs/install/index.md | 22 +++ docs/install/limited-mode.md | 86 +++++++++++ docs/install/native-mode.md | 251 +++++++++++++++++++++++++++++++++ docs/introduction.md | 38 +++++ 15 files changed, 693 insertions(+), 347 deletions(-) delete mode 100644 docs/Bare-Metal.md delete mode 100644 docs/Integrated-Mode.md delete mode 120000 docs/README.md delete mode 100644 docs/Simple-Mode.md create mode 100644 docs/features/agent.md create mode 100644 docs/features/sso.md create mode 100644 docs/getting-started.md create mode 100644 docs/install/docker.md create mode 100644 docs/install/index.md create mode 100644 docs/install/limited-mode.md create mode 100644 docs/install/native-mode.md create mode 100644 docs/introduction.md diff --git a/README.md b/README.md index 01e16c2..cb12ae0 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 1765216..57664d7 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -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' }, diff --git a/docs/Bare-Metal.md b/docs/Bare-Metal.md deleted file mode 100644 index e8a1725..0000000 --- a/docs/Bare-Metal.md +++ /dev/null @@ -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. diff --git a/docs/Integrated-Mode.md b/docs/Integrated-Mode.md deleted file mode 100644 index 85e5709..0000000 --- a/docs/Integrated-Mode.md +++ /dev/null @@ -1,199 +0,0 @@ -# Integrated Mode - - - - - Integration Preview - - -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 -``` diff --git a/docs/README.md b/docs/README.md deleted file mode 120000 index 3dfb7d7..0000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -./../README.md \ No newline at end of file diff --git a/docs/Simple-Mode.md b/docs/Simple-Mode.md deleted file mode 100644 index 2660a44..0000000 --- a/docs/Simple-Mode.md +++ /dev/null @@ -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. diff --git a/docs/features/agent.md b/docs/features/agent.md new file mode 100644 index 0000000..fc06cf2 --- /dev/null +++ b/docs/features/agent.md @@ -0,0 +1,7 @@ +--- +title: Headplane Agent +description: Configure the Headplane Agent for enhanced functionality. +--- + +# Headplane Agent +TODO diff --git a/docs/features/sso.md b/docs/features/sso.md new file mode 100644 index 0000000..e9be232 --- /dev/null +++ b/docs/features/sso.md @@ -0,0 +1,7 @@ +--- +title: Single Sign-On (SSO) +description: Configure Single Sign-On (SSO) authentication for Headplane. +--- + +# Single Sign-On (SSO) +TODO diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md index b7272b5..cf5890d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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" diff --git a/docs/install/docker.md b/docs/install/docker.md new file mode 100644 index 0000000..2443569 --- /dev/null +++ b/docs/install/docker.md @@ -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. + +
+Traefik config snippet + +```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' +``` +
+ diff --git a/docs/install/index.md b/docs/install/index.md new file mode 100644 index 0000000..04200c4 --- /dev/null +++ b/docs/install/index.md @@ -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. | diff --git a/docs/install/limited-mode.md b/docs/install/limited-mode.md new file mode 100644 index 0000000..bfcdf6d --- /dev/null +++ b/docs/install/limited-mode.md @@ -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. + +
+Example Docker Compose configuration + +```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' +``` +
+ +## 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. + diff --git a/docs/install/native-mode.md b/docs/install/native-mode.md new file mode 100644 index 0000000..62f86f5 --- /dev/null +++ b/docs/install/native-mode.md @@ -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. + +
+Example Systemd service file + +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 +``` +
+ +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. + +
+Nginx config snippet + +```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; + } +} +``` +
+ +## 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. diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 0000000..4fb3fa3 --- /dev/null +++ b/docs/introduction.md @@ -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. + + + + +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. + + + + +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