mode lectureenv. 6 minjinx.proc tourneshader tz europe/parisenfr
~/boops/headscale-on-nixos
2024 — 07 — 21·nixos · réseau · self-host·wip

mettre en place headscale sur nixos

installer un serveur headscale et y connecter des nœuds tailscale

kay@borg:~/boops$ cat headscale-on-nixos.md | bat
// pourquoi ?

j'ai migré récemment toutes mes machines vers nix et nixos — desktop, laptop, vps, téléphone (nix-on-droid). je voulais un vpn pour qu'elles puissent toutes se joindre entre elles sans tracas, et headscale semblait assez populaire pour valoir le coup.

comment ?

prérequis

1. récupère un domaine. j'utilise headscale.juke.fr ; configure un enregistrement Aqui pointe vers la machine qui hébergera headscale. tu peux aussi utiliser un service de dns dynamique, mais c'est hors scope ici — regarde ddclientsi c'est ton plan.

2. ouvre 80/tcp, 443/tcp et 3478/udpsur le firewall de l'hôte. la config nixos plus bas s'en occupe pour nous, mais sur un vps (le mien est sur l'offre gratuite oracle) il faudra peut-être les ouvrir en amont aussi.

// configuration nixos headscale

crée un module headscale.nix que tu importes dans ta config nixos. à ajuster selon ton goût :

{
  config,
  ...
}:
let
  domain = "juke.fr"; # domain to use
  derpPort = 3478; # default derp port
in
{
  services = {
    # enable headscale service and configure
    headscale = {
      enable = true;
      address = "127.0.0.1";
      port = 8085;
      settings = {
        dns_config = {
          override_local_dns = true;
          base_domain = domain;
          magic_dns = true;
          domains = [ "hs.${domain}" ];
          nameservers = [
            "1.1.1.1"
            "9.9.9.9"
          ];
        };
        server_url = "https://headscale.${domain}";
        metrics_listen_addr = "127.0.0.1:8095";
        derp.server = {
          enable = true;
          region_id = 999;
          stun_listen_addr = "0.0.0.0:${toString derpPort}";
        };
      };
    };

    # reverse proxy with ssl
    nginx = {
      enable = true;
      virtualHosts."headscale.${domain}" = {
        forceSSL = true;
        enableACME = true;
        locations = {
          "/" = {
            proxyPass = "http://localhost:${toString config.services.headscale.port}";
            proxyWebsockets = true;
          };
          "/metrics" = {
            proxyPass = "http://${config.services.headscale.settings.metrics_listen_addr}/metrics";
          };
        };
      };
    };
  };

  # configure ssl certificate options
  security.acme = {
    defaults.email = "acme@juke.fr";
    acceptTerms = true;
  };

  # punch through firewall
  networking.firewall.allowedUDPPorts = [ derpPort ];
  networking.firewall.allowedTCPPorts = [ 80 443 ];

  environment.systemPackages = [ config.services.headscale.package ];
}

bascule ta config nixos et vérifie que tout fonctionne en allant sur headscale.juke.fr/metrics. il faut aussi créer un namespace (qui sert également d'utilisateur) pour la suite :

$sudo headscale namespaces create net # remplace `net` par ce que tu veux
// configuration nixos tailscale

mets en place le service tailscale dans tailscale.nix et importe-le dans ta config commune pour que chaque machine l'ait :

{
  lib,
  ...
}:
{
  services.tailscale = {
    enable = true;
    useRoutingFeatures = lib.mkDefault "client";
  };
  networking.firewall = {
    checkReversePath = "loose";
    allowedUDPPorts = [ 41641 ]; # facilitate firewall punching
  };
}

rebuild nixos. on peut maintenant rejoindre l'instance headscale :

$sudo tailscale up --login-server https://headscale.juke.fr

tu vas recevoir une url de login qui affiche une commande à exécuter sur la machine headscale (en remplaçant $USERpar le namespace créé plus haut). n'oublie pas le sudo.

pour finir

ta machine est maintenant accessible via $HOST.$NAMESPACE.$DOMAIN — par exemple nixos-home.net.juke.fr. voilà, c'est à peu près tout. merci pour la lecture.

une voix plus naturelle sur linuxretour accueil