Aller au contenu

Le VPN (Headscale / Tailscale)

Le VPN maille toutes les zones et les machines distantes : Headscale 🡕 coordonne (sur le HCS), Tailscale 🡕 est le client sur chaque nœud. Vue d’ensemble dans Réseau.

Activer la coordination et déclarer le HCS (profile: hcs) suffit :

etc/config.yaml
network:
coordination:
enable: true
hostname: "hcs"
domain: "headscale"

Les rôles se déduisent du profil de chaque hôte :

  • HCS : coordination du maillage (Headscale).
  • Passerelle : subnet router + exit node : publie le sous-réseau de sa zone.
  • Autres nœuds : clients Tailscale.

Toutes les machines rejoignent le maillage via un utilisateur Headscale d’attache partagé (nix). Il se crée une seule fois pour tout le réseau ; s’il existe déjà, passer cette étape.

Fenêtre de terminal
just enter hcs
sudo headscale users list # déjà présent ? → rien à faire
sudo headscale users create nix --display-name "Nix Admin" --email "nix@domain.tld"

Le profil gateway fait déjà de la passerelle un client Tailscale : au déploiement, le service tailscaled-autoconnect l’enregistre tout seul sur Headscale et annonce le sous-réseau de sa zone. Il reste deux gestes manuels : fournir une clé d’attache dans sops (avant le déploiement) et approuver les routes sur le HCS (après).

  1. Sur le HCS : générer une clé d’attache

    Fenêtre de terminal
    just enter hcs
    sudo headscale users list # ID de l'utilisateur nix
    sudo headscale preauthkeys create --reusable --expiration 1h --user <id>

    Copier la clé affichée (tskey-...). Elle n’a besoin de vivre que le temps du déploiement.

  2. Déposer la clé dans les secrets

    Fenêtre de terminal
    just sops # ouvre usr/secrets/secrets.yaml

    Renseigner la clé sous tailscale/authKey :

    usr/secrets/secrets.yaml
    tailscale:
    authKey: "tskey-..."
  3. Déployer la passerelle

    Fenêtre de terminal
    just apply gw

    La passerelle s’enregistre automatiquement. En interne, le démon exécute :

    Fenêtre de terminal
    tailscale up \
    --login-server https://headscale.domain.tld \
    --auth-key file:/run/secrets/tailscale/authKey \
    --advertise-routes 10.0.0.0/16 --accept-routes --reset
  4. Sur le HCS : approuver les routes annoncées

    Fenêtre de terminal
    sudo headscale nodes list # ID de la passerelle
    sudo headscale nodes approve-routes --identifier <id> --routes 10.0.0.0/16
  5. Déclarer l’IP tailnet de la passerelle

    À l’enregistrement, Headscale attribue à la passerelle une IP tailnet (100.64.x.y), visible dans headscale nodes list. La reporter dans etc/config.yaml : les autres nœuds joignent la zone (DNS interne, réplication, supervision) par cette adresse.

    etc/config.yaml
    zones:
    maison:
    gateway:
    vpn:
    ipv4: "100.64.0.8"

    Puis régénérer et redéployer les nœuds concernés (le HCS et les clients de la zone) pour propager l’adresse.

La commande headscale (alias h = sudo headscale) sur le HCS :

Fenêtre de terminal
sudo headscale users list # utilisateurs
sudo headscale nodes list # clients connectés
sudo headscale nodes routes # routes annoncées / approuvées

Un tailscaled peut décrocher silencieusement de Headscale : la connexion de contrôle est perdue alors que le service reste « actif », et le sous-réseau d’une passerelle devient injoignable jusqu’à un redémarrage manuel. Un watchdog local détecte et corrige ce cas, sur chaque client Tailscale.

AspectComportement
Sondetoutes les 60 s : tailscale status (backend, état en ligne, santé)
Anti-rebond3 sondes en échec d’affilée (~3 min) avant d’agir : encaisse les coupures WAN passagères
Correctionsystemctl restart tailscaled (ré-enregistrement automatique sur Headscale)
Anti-boucleune seule correction par fenêtre de 10 min
Observabilitémétriques dnf_tailscale_healthy et dnf_tailscale_selfheal_restarts_total (textfile node_exporter)

Deux alertes accompagnent le mécanisme :

  • TailscaleUnhealthy : toujours décroché malgré la correction (problème de fond) ;
  • TailscaleFlapping : l’auto-réparation se répète trop souvent (cause à traiter).

Le nom du serveur Headscale se résout normalement à travers le tailnet : sur une passerelle, dnsmasq route tout le domaine du réseau vers le serveur DNS du tailnet. Le client aurait donc besoin du VPN pour joindre le serveur qui monte le VPN — et au démarrage, le résolveur local n’écoute pas encore.

Chaque client Tailscale reçoit donc l’IP publique du HCS dans son /etc/hosts, déduite de etc/config.yaml (le HCS lui-même est exclu) :

Fenêtre de terminal
grep headscale /etc/hosts # 217.182.207.26 headscale.example.org

Le client n’a ainsi besoin d’aucun résolveur pour se connecter, y compris quand le DNS local est en panne — précisément le moment où l’auto-réparation ci-dessus doit pouvoir agir.

Pour rejoindre le réseau hors d’une zone, voir Se connecter depuis l’extérieur.