Skip to main content
Headplane is a modern web-based GUI for managing your Headscale server, providing an intuitive alternative to command-line management.

Accessing Headplane

Headplane is included in the Docker stack and runs automatically: URL: http://localhost:3001/admin/
Make sure to include the trailing slash (/admin/). Without it, you’ll get a 404 error.

Initial Setup

1

Generate an API key

docker exec headscale headscale apikeys create --expiration 999d
Copy the generated key (it’s shown only once).
2

Open Headplane in browser

3

Login with API key

Paste the API key into the login form and click Login.

Dashboard

The dashboard provides an overview of your entire network:

Network Overview

  • Total nodes connected
  • Online/offline status
  • Active users
  • Recent activity

Quick Stats

  • Number of nodes per user
  • Active routes
  • Pre-auth keys created
  • System health

Recent Events

  • New nodes connected
  • Routes advertised
  • Keys created
  • Configuration changes

Health Status

  • Headscale service status
  • Database connectivity
  • API availability
  • Version information

Managing Nodes

View All Nodes

  1. Click Nodes in the sidebar
  2. See all connected devices with:
    • Hostname
    • User/owner
    • IP addresses (IPv4 and IPv6)
    • Online/offline status
    • Last seen timestamp
    • Operating system
    • Tags

Node Details

Click any node to view detailed information:
  • Full hostname
  • Node ID
  • User/namespace
  • Created date
  • Last updated
  • Tailscale version
  • OS and architecture

Node Actions

Rename

  1. Click node name
  2. Edit hostname field
  3. Save changes

Delete

  1. Select node
  2. Click Delete button
  3. Confirm deletion
This removes the node from the network. It must reconnect with a new key.

Expire

  1. Select node
  2. Click Expire
  3. Node is marked as expired
Useful for temporarily disabling access.

Tag

  1. Click node
  2. Go to Tags section
  3. Add or remove tags
  4. Save changes

Managing Users

View Users

  1. Click Users in sidebar
  2. See all users with:
    • Username
    • Number of nodes
    • Created date
    • Node list preview

Create User

1

Click 'Create User'

In the Users page, click the Create User button.
2

Enter username

Type the username (lowercase, no spaces recommended).
3

Save

Click Save to create the user.
4

Generate keys

Create pre-auth keys for the new user to connect devices.

User Actions

  • View nodes: Click username to see all their devices
  • Delete user: Remove user and all associated nodes
  • Generate keys: Create pre-auth keys for the user

Pre-Auth Key Management

Create Pre-Auth Key

1

Navigate to Pre-Auth Keys

Click Pre-Auth Keys in the sidebar.
2

Click 'Create New Key'

Button is at the top of the page.
3

Configure key settings

  • User: Select which user owns this key
  • Expiration: Set how long the key is valid
    • 1 hour (production)
    • 24 hours (testing)
    • 168 hours (7 days)
    • Custom duration
4

Create and copy key

  1. Click Create
  2. Copy the generated key immediately
  3. Store it securely
The key is shown only once. You cannot retrieve it later.

View Active Keys

See all pre-auth keys:
  • Key prefix (last few characters)
  • User/owner
  • Created date
  • Expiration date
  • Reusable status
  • Used/unused status

Expire Key

  1. Find the key in the list
  2. Click Expire button
  3. Key is immediately invalidated
  4. Cannot be used to connect new devices

Route Management

View Routes

  1. Click Routes in sidebar
  2. See all advertised routes:
    • Node advertising the route
    • Subnet/prefix (e.g., 192.168.1.0/24)
    • Exit node routes (0.0.0.0/0)
    • Enabled/disabled status

Approve Routes

1

Find the route

Routes are listed with their advertising node and prefix.
2

Click 'Approve' or 'Enable'

Button appears next to disabled routes.
3

Verify activation

The route status changes to Enabled and clients can now use it.

Approve Exit Nodes

Exit node routes are shown as 0.0.0.0/0 (IPv4) or ::/0 (IPv6):
  1. Find exit node route
  2. Click Approve
  3. Node can now route internet traffic

Disable Route

  1. Find enabled route
  2. Click Disable
  3. Clients can no longer use this route

ACL Policy Editor

Edit Policies

1

Navigate to Policies/Settings

Click Policies or Settings in sidebar.
2

Edit policy JSON

Use the built-in editor to modify policy.json:
{
  "tagOwners": {
    "tag:personal": ["group:admins"],
    "tag:servers": ["group:admins"]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["tag:personal"],
      "dst": ["tag:servers:22,80,443"]
    }
  ]
}
3

Validate syntax

The editor highlights JSON syntax errors.
4

Save changes

Click Save to apply the new policy.

Policy Examples

{
  "tagOwners": {
    "tag:personal": ["group:admins"],
    "tag:servers": ["group:admins"]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["tag:personal"],
      "dst": ["tag:servers:*"]
    }
  ]
}

API Keys Management

Create Additional API Keys

  1. Go to Settings or API Keys
  2. Click Create API Key
  3. Set expiration (recommended: 365 days)
  4. Copy and store the key securely

Revoke API Key

Revoking an API key will log out any sessions using that key.
  1. Find the key in the list
  2. Click Revoke or Delete
  3. Confirm revocation

Headplane Configuration

Headplane settings are in headplane/config.yaml:
headplane/config.yaml
headscale_url: http://headscale:8080
api_key: YOUR_API_KEY_HERE
cookie_secret: exactly_32_character_string_
log_level: info

Configuration Options

OptionDescriptionExample
headscale_urlInternal Headscale URLhttp://headscale:8080
api_keyHeadscale API keyGenerated from headscale apikeys create
cookie_secretSession encryption key32-character string
log_levelLogging verbosityinfo, debug, warn

Troubleshooting

404 Error When Accessing Headplane

1

Check URL has trailing slash

✅ Correct: http://localhost:3001/admin/❌ Wrong: http://localhost:3001
2

Verify Headplane is running

docker compose ps | grep headplane
# Should show "Up"
3

Check logs

docker compose logs headplane --tail 50

Cannot Login / Invalid API Key

1

Generate new API key

docker exec headscale headscale apikeys create --expiration 999d
2

Update Headplane config

Edit headplane/config.yaml and add the new key:
api_key: NEW_KEY_HERE
3

Restart Headplane

docker compose restart headplane

Headplane Not Loading / Blank Page

# Check Headscale is running
curl http://localhost:8000/health
# Should return: {"status":"pass"}

# Verify API key works
docker exec headscale headscale nodes list

# Check cookie_secret is exactly 32 characters
grep cookie_secret headplane/config.yaml

# Restart both services
docker compose restart headscale headplane

Changes Not Appearing

  1. Hard refresh browser: Ctrl+Shift+R (or Cmd+Shift+R on Mac)
  2. Clear browser cache: Settings → Clear browsing data
  3. Check service logs: docker compose logs headplane

GUI vs Command Line

Best for:
  • Visual overview of network
  • Quick device management
  • Non-technical users
  • One-off tasks
  • Monitoring status
Advantages:
  • No terminal needed
  • Visual feedback
  • Easy navigation
  • Real-time updates

Security Best Practices

Secure API Keys

  • Use long expiration only for dev: --expiration 999d
  • Production keys: --expiration 90d
  • Rotate keys regularly
  • Never commit keys to git

Network Access

  • Don’t expose Headplane publicly
  • Use VPN or Tailscale to access it
  • Add authentication proxy if needed
  • Monitor access logs

Cookie Security

  • Use strong 32-character cookie_secret
  • Change default secret
  • Use random string generator:
openssl rand -base64 32

Regular Audits

  • Review connected nodes weekly
  • Check active API keys
  • Audit user access
  • Remove unused keys and nodes

Tips and Tricks

Keyboard Shortcuts

  • Search nodes: Type in search box (usually / key)
  • Refresh data: F5 or refresh button
  • Navigate: Use browser back/forward

Bulk Operations

For bulk operations, use command line:
# Delete multiple nodes
for id in 1 2 3 4 5; do
  docker exec headscale headscale nodes delete --identifier $id
done

# Create multiple users
for user in alice bob charlie; do
  docker exec headscale headscale users create $user
done

Export Data

# Export node list
docker exec headscale headscale nodes list > nodes.txt

# Export users
docker exec headscale headscale users list > users.txt

# Export routes
docker exec headscale headscale routes list > routes.txt

Next Steps

Build docs developers (and LLMs) love