Docs

Install: Headscale client

Step-by-step installer for Debian / Raspberry Pi OS — includes Tailscale, subnet advertisement and security tooling.

Overview

This page documents the Purplerain Headscale client auto-setup script. It installs Tailscale, applies interface optimizations, advertises local subnets to your Headscale server, and installs security tools like Nmap and Suricata.

Where to get the script

Script URL: https://purplerain.tech/scripts/purplerain-headscale-client-setup.sh

Checksum (SHA256): purplerain-headscale-client-setup.sh.sha256

Download, verify, run (recommended)

Verify the checksum before running. This sequence downloads the script and its checksum, verifies integrity, then runs the installer.

curl -fsSL https://purplerain.tech/scripts/purplerain-headscale-client-setup.sh -o /tmp/purplerain-headscale-client-setup.sh
curl -fsSL https://purplerain.tech/scripts/purplerain-headscale-client-setup.sh.sha256 -o /tmp/purplerain-headscale-client-setup.sh.sha256
sha256sum --check /tmp/purplerain-headscale-client-setup.sh.sha256
sudo bash /tmp/purplerain-headscale-client-setup.sh

If the checksum verification fails, do not run the script. Contact support or fetch a fresh copy over HTTPS.

Non-interactive / automation

For CI or unattended installs set the environment variable PURPLERAIN_AUTH_KEY to your Headscale preauth key before running the script:

export PURPLERAIN_AUTH_KEY="your_pre_auth_key_here"
curl -fsSL https://purplerain.tech/scripts/purplerain-headscale-client-setup.sh | sudo -E bash

Interactive install and saving the key

If you run the script interactively it will prompt for the Headscale preauth key and offer to save it to /etc/purplerain/headscale_auth (root-only). This avoids editing the script for subsequent runs.

What the script does (summary)

  • Installs Tailscale from upstream packages and configures it to use your Headscale login server.
  • Enables IP forwarding (IPv4/IPv6) for subnet routing.
  • Applies ethtool UDP-GRO optimizations to all active, non-loopback interfaces and creates a systemd oneshot to reapply them on boot.
  • Auto-detects local subnets and advertises them to Headscale.
  • Installs security tools: Nmap, Masscan, Nikto, Suricata, tcpdump, tshark, etc., and configures Suricata to monitor a detected interface.
  • Creates convenient aliases for quick scanning and Suricata log access.

Front-end checksum verification (optional)

You can add a browser-side verification widget that fetches both the script and the .sha256 file and compares the SHA256 using SubtleCrypto. This is a convenience for users visiting the site; it relies on HTTPS and the integrity of the host page.

<script>
async function verifyScript() {
  const scriptUrl = '/scripts/purplerain-headscale-client-setup.sh';
  const checksumUrl = '/scripts/purplerain-headscale-client-setup.sh.sha256';

  const [scriptResp, sumResp] = await Promise.all([fetch(scriptUrl), fetch(checksumUrl)]);
  if (!scriptResp.ok || !sumResp.ok) return false;
  const scriptBuf = await scriptResp.arrayBuffer();
  const sumText = await sumResp.text();
  const expected = sumText.split(/s+/)[0].toLowerCase();

  const hashBuf = await crypto.subtle.digest('SHA-256', scriptBuf);
  const hashArray = Array.from(new Uint8Array(hashBuf));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2,'0')).join('');

  return hashHex === expected;
}

verifyScript().then(ok => {
  if (ok) console.log('Script checksum OK');
  else console.warn('Script checksum mismatch');
});
</script>

Note: front-end verification is best-effort — for stronger guarantees publish signed releases (GPG) and verify signatures.

Troubleshooting

  • If no local subnets are detected the script will exit with an error; ensure your interfaces have addresses and try again.
  • If Suricata's config layout differs the script will warn and you may need to manually set the interface in /etc/suricata/suricata.yaml.
  • Check journal logs for systemd services: sudo journalctl -u purplerain-ethtool.service and sudo journalctl -u suricata.