Here I will walk you through setting up Headscale


Create Directories

mkdir -p /opt/headscale/config /opt/headscale/bin


Install Reqs

apt install -y wireguard-tools nginx apt-transport-https


Generate Key

wg genkey > /opt/headscale/config/private.key


  1. Download newest release from HERE

  2. wget https://github.com/juanfont/headscale/releases/download/v0.10.8/headscale_0.10.8_linux_amd64 -O /opt/headscale/bin/headscale

  3. Add headscale ~/.bashrc echo PATH=$PATH:/opt/headscale/bin >> ~/.bashrc

  4. Source the new PATH source ~/.bashrc


Download darp file

wget https://raw.githubusercontent.com/juanfont/headscale/main/derp.yaml -O /opt/headscale/config/derp.yaml


Create config

Create a config in /opt/headscale/config/config.yml

nano config.yaml

server_url: http://headscale.domain.com
listen_addr: 127.0.0.1:8080
ip_prefix: 100.64.0.0/10
disable_check_updates: false
private_key_path: private.key
db_type: sqlite3
db_path: db.sqlite
ephemeral_node_inactivity_timeout: "30m"
derp_map_path: derp.yaml
dns_config:
  nameservers:
    - 1.1.1.1
    - 8.8.8.8
#  restricted_nameservers:
#    foo.bar.com:
#      - 1.1.1.1
#    darp.headscale.net:
#      - 1.1.1.1
#      - 8.8.8.8
  domains: []
  magic_dns: true
  base_domain: domain.com

Create systemd script

nano /etc/systemd/system/headscale.service

[Unit]
Description=headscale
After=network.target

[Service]
WorkingDirectory=/opt/headscale/config
ExecStart=/opt/headscale/bin/headscale serve
# Disable debug mode
Environment=GIN_MODE=release

[Install]
WantedBy=multi-user.target

Now we can start the headscale service systemctl enable --now headscale.service


Now it’s time to configure NGiNX

Unlink default config unlink /etc/nginx/sites-enabled/default

Create new headscale config nano /etc/nginx/conf.d/headscale.domain.com.conf

server {
  listen 80;
  server_name headscale.domain.com;
  return 301 https://headscale.domain.com$request_uri;
}

server {
  server_name headscale.domain.com;

  client_body_timeout 5m;
  client_header_timeout 5m;

  access_log            /var/log/nginx/foobar.example.com.access.log;
  error_log            /var/log/nginx/foobar.example.com.error.log info;

  # reverse proxy
  location / {
     proxy_pass http://127.0.0.1:8080;  # headscale listen_addr
     proxy_read_timeout 6m;
     proxy_ignore_client_abort off;
     proxy_request_buffering off;
     proxy_buffering off;
     proxy_no_cache "always";
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }


  listen 443 ssl http2;
  ssl_certificate       /etc/nginx/ssl/headscale.domain.com/fullchain.crt;
  ssl_certificate_key   /etc/nginx/ssl/headscale.domain.com/key;
}

Now it’s time to configure UFW

ufw allow http ufw allow https


Now it’s time to install tailscale. Below is a useful script to do so

#!/bin/bash

apt-get update
apt-get install -y apt-transport-https gnupg2

# Add the Tailscale repo

source /etc/os-release

test $VERSION_ID = "7" && versionName="wheezy"
test $VERSION_ID = "8" && versionName="jessie"
test $VERSION_ID = "9" && versionname="stretch"
test $VERSION_ID = "10" && versionName="buster"
test $VERSION_ID = "11" && versionName="bullseye"

curl -fsSL https://pkgs.tailscale.com/stable/debian/${versionName}.gpg | apt-key add -
curl -fsSL https://pkgs.tailscale.com/stable/debian/${versionName}.list | tee /etc/apt/sources.list.d/tailscale.list

apt-get update
apt-get install -y tailscale

tailscale up --login-server https://headscale.domain.com

This should give you a URL to go to. It will tell you what to time into the headscale CLI. Make sure your in the /opt/headscale/config directory and follow the link.


If you’d like to script adding it you can use the script below and just use the KEY part of the URL. This will be ran as script network_name node_key. This will auto add the node to the network

#!/bin/bash

network=$1
key=$2

data=$(curl -s "https://headscale.domain.com/register?key=${key}")
command=$(echo "${data}" | grep '<b>' | grep headscale | cut -d'>' -f2 | cut -d'<' -f1 | sed "s/NAMESPACE/$network/g")
$command