Skip to Content
Getting started

Getting started

Headtower needs two things to come online: the URL of a reachable Headscale instance, and an API key it can use to talk to it. Everything else is optional.

Prerequisites

  • A running Headscale control plane that Headtower can reach over the network.
  • A Headscale API key (Headtower authenticates to the control plane with it).
  • Node.js 22.5+ (24 recommended) and pnpm if you are running from source - Headtower uses the built-in node:sqlite, which needs 22.5 or newer.

Generate an API key from your Headscale host with headscale apikeys create. Treat it like a password - it grants full control-plane access.

Install and run

Get the code

git clone https://github.com/rnihesh/headtower.git cd headtower pnpm install

Set the environment

Headtower reads its configuration from the environment. Only two variables are required to start:

export HEADSCALE_URL="https://headscale.example.com" export HEADSCALE_API_KEY="<your-headscale-api-key>"

You can also drop these into a .env.local file at the project root.

Start the console

pnpm dev

Open http://localhost:3000 . Headtower opens on the Machines readout - the core operational view.

You don’t have to set these at all. Start Headtower with no connection and it opens a /setup wizard to enter and test the Headscale URL and API key in the browser. Setting the env vars just skips that step. A value you do provide is validated - a malformed HEADSCALE_URL is named rather than silently ignored.

Run with Docker

For a long-running deployment, use Docker Compose - it wires the app, its persistent volume, and the optional agent together:

git clone https://github.com/rnihesh/headtower.git cd headtower cp .env.example .env # set HEADSCALE_URL + HEADSCALE_API_KEY at minimum docker compose up -d

Open http://<your-host>:3000. The named volume (/app/data in the container) keeps Headtower’s own state - operators, roles, audit log - across restarts. See Configuration for the full set of variables, including single sign-on and the agent.

The browser SSH terminal and device metadata come from an optional agent, off by default. Enable it with docker compose --profile agent up -d after setting HEADTOWER_AGENT_AUTHKEY and HEADTOWER_AGENT_LOGIN_SERVER in .env.

Headscale remains the source of truth for tailnet data. The Headtower volume only persists Headtower-specific state, so it is safe to recreate the container as long as the volume is preserved.

Next steps

  • Skim the Concepts so the vocabulary lines up with Headscale.
  • Walk the Features to see what each view does.
  • Lock down access and sign-in in Configuration.
Last updated on