How to set up Headscale
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
-
Download newest release from HERE
-
wget https://github.com/juanfont/headscale/releases/download/v0.15.0-beta5/headscale_0.15.0-beta5_linux_amd64 -O /opt/headscale/bin/headscale
-
Add headscale ~/.bashrc
echo PATH=$PATH:/opt/headscale/bin >> ~/.bashrc
-
Source the new PATH
source ~/.bashrc
Create config⌗
Create a config in /opt/headscale/config/config.yml
nano config.yaml
---
# The url clients will connect to.
# Typically this will be a domain.
server_url: https://headscale.domain.com
# Address to listen to / bind to on the server
listen_addr: 127.0.0.1:8080
# Address to listen to /metrics, you may want
# to keep this endpoint private to your internal
# network
#
metrics_listen_addr: 127.0.0.1:9090
# Address to listen for gRPC.
# gRPC is used for controlling a headscale server
# remotely with the CLI
# Note: Remote access _only_ works if you have
# valid certificates.
grpc_listen_addr: 127.0.0.1:50443
# Allow the gRPC admin interface to run in INSECURE
# mode. This is not recommended as the traffic will
# be unencrypted. Only enable if you know what you
# are doing.
grpc_allow_insecure: true
# Path to WireGuard private key file
private_key_path: /opt/headscale/data/private.key
ip_prefixes: 100.64.0.0/10
# DERP is a relay system that Tailscale uses when a direct
# connection cannot be established.
# https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
#
# headscale needs a list of DERP servers that can be presented
# to the clients.
derp:
server:
# If enabled, runs the embedded DERP server and
# merges it into the rest of the DERP config
# The Headscale server_url defined above MUST
# be using https, DERP requires TLS to be in place
enabled: true
# Region ID to use for the embedded DERP server.
# The local DERP prevails if the region ID collides
# with other region ID coming from
# the regular DERP config.
region_id: 999
# Region code and name are displayed in
# the Tailscale UI to identify a DERP region
region_code: "name01"
region_name: "Domain DERP 01"
# If enabled, also listens in UDP at the configured address
# for STUN connections to help on NAT traversal
# For more details on how this works
# check this great article: https://tailscale.com/blog/how-tailscale-works/
stun:
enabled: true
listen_addr: "0.0.0.0:3478"
# List of externally available DERP maps encoded in JSON
#urls:
# - https://controlplane.tailscale.com/derpmap/default
# Locally available DERP map files encoded in YAML
#
# This option is mostly interesting for people hosting
# their own DERP servers:
# https://tailscale.com/kb/1118/custom-derp-servers/
#
# paths:
# - /etc/headscale/derp-example.yaml
paths: []
# If enabled, a worker will be set up to periodically
# refresh the given sources and update the derpmap
# will be set up.
auto_update_enabled: true
# How often should we check for updates?
update_frequency: 24h
# Disables the automatic check for updates on startup
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
# SQLite config
db_type: sqlite3
db_path: /opt/headscale/data/db.sql
# # Postgres config
# db_type: postgres
# db_host: localhost
# db_port: 5432
# db_name: headscale
# db_user: foo
# db_pass: bar
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
#tls_letsencrypt_hostname: ""
#tls_letsencrypt_listen: ":http"
#tls_letsencrypt_cache_dir: ".cache"
#tls_letsencrypt_challenge_type: HTTP-01
#tls_cert_path: ""
#tls_key_path: ""
# Path to a file containg ACL policies.
acl_policy_path: "/opt/headscale/config/acls.yaml"
#acl_policy_path: "/opt/headscale/config/acls.hjson"
#dns_config:
# # Upstream DNS servers
# nameservers:
# - 100.64.0.1
# - 107.152.39.57
# 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;
#Websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# API access
location /headscale {
grpc_pass grpc://127.0.0.1:50443;
}
# reverse proxy
location /metrics {
proxy_pass http://127.0.0.1:9090/metrics; # 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;
auth_basic "Password please";
auth_basic_user_file /etc/nginx/passwd/headscale-metrics;
}
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