From 70e59c2f61d714219087b779a74a9a9c395b9eb5 Mon Sep 17 00:00:00 2001 From: Ssyleric <47066760+Ssyleric@users.noreply.github.com> Date: Sun, 14 Dec 2025 22:38:07 +0100 Subject: [PATCH] Update README.md --- README.md | 436 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 435 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e5bf8d1..aa62ead 100644 --- a/README.md +++ b/README.md @@ -1 +1,435 @@ -# Tailscale2Headscale \ No newline at end of file +# Tailscale2Headscale +# Headscale + Tailscale – Homelab Migration + +> ⚠️ **Version publique / anonymisée** +> Tous les noms de domaine, IP et clés ont été remplacés par des **placeholders**. +> Remplace toutes les valeurs `<...>` par les tiennes avant d’utiliser ce document. + +--- + +## 1. Objectif + +Mettre en place un **contrôle Tailscale auto‑hébergé** avec **Headscale** pour remplacer le control plane Tailscale SaaS, tout en : + +- gardant les clients Tailscale classiques (Linux, macOS, Android, Home Assistant, etc.) ; +- centralisant la gestion sur un serveur Headscale accessible en HTTPS ; +- évitant les bugs classiques (mauvais port, mauvais `--login-server`, clés expirées, etc.). + +Ce README récapitule : + +- l’architecture retenue ; +- la configuration Headscale (service + Web admin + reverse proxy) ; +- la configuration des clients Tailscale ; +- les problèmes rencontrés et les solutions pour ne plus tomber dedans. + +--- + +## 2. Architecture globale + +### 2.1. Composants + +- **Serveur Headscale** + + - Type : LXC / VM Linux (Debian‑like) + - Rôle : serveur `headscale` + Web UI (headscale‑admin) + - IP locale : `` (ex : `192.168.1.xxx`) + - Nom interne : `` (ex : `headscale`) +- **Reverse proxy (facultatif mais recommandé)** + + - Logiciel : `caddy` (ou nginx/traefik) + - Port HTTP interne Headscale : `8080` + - Port HTTPS public : `443` + - Nom de domaine : `` (ex : `headscale.example.com`) + - Certificats : Let’s Encrypt ou équivalent +- **Clients Tailscale** + + - Serveur Proxmox VE : `` + - Proxmox Backup Server : `` + - NAS (OMV ou autre) : `` + - Containers / VM : ``, ``, etc. + - Home Assistant : Add-on Tailscale + - macOS : client Tailscale officiel + - Android : app Tailscale officielle + +Tout ce petit monde parle au **contrôle plane** : `https://`. + +--- + +## 3. Installation de Headscale (serveur) + +### 3.1. Pré‑requis + +Sur la machine Headscale (LXC/VM) : + +```bash +apt update +apt install -y headscale sqlite3 ca-certificates curl +``` + +Créer le répertoire de configuration : + +```bash +mkdir -p /etc/headscale +``` + +### 3.2. Fichier de configuration `config.yaml` (exemple) + +> ⚠️ **Important :** Adapter les valeurs `server_url`, `listen_addr`, `grpc_listen_addr`, `db_path`, etc. + +```yaml +# /etc/headscale/config.yaml +server_url: "https://" +listen_addr: "0.0.0.0:8080" +grpc_listen_addr: "0.0.0.0:50443" + +ip_prefixes: + - "100.64.0.0/10" + +derp: + server: + enabled: true + region_id: 999 + region_code: "homelab" + region_name: "Homelab DERP" + paths: [] + +# Base SQLite (simple à gérer pour un homelab) +db_type: "sqlite" +db_path: "/var/lib/headscale/db.sqlite" + +tls_cert_path: "" +tls_key_path: "" + +log: + level: "info" + +dns_config: + override_local_dns: false + magic_dns: false +``` + +### 3.3. Service systemd + +Le paquet Debian fournit généralement un service `headscale.service`. +Vérifier : + +```bash +systemctl enable --now headscale +systemctl status headscale --no-pager +``` + +--- + +## 4. Web admin : headscale‑admin + +### 4.1. Dossier et configuration + +Headscale‑admin est en général servi par un serveur web (caddy/nginx), souvent depuis : + +```bash +/var/www/headscale-admin +``` + +ou : + +```bash +/opt/headscale-admin +``` + +Cette UI se connecte à l’API Headscale (port `8080` dans notre cas). + +--- + +## 5. Reverse proxy (Caddy) + +> C’est ici qu’on a eu une galère : mélange de ports `80` et `8080`. +> Résultat : clients Tailscale qui pointaient sur `:8080` alors que le proxy écoutait en `:80` → 404 ou connexion impossible. + +### 5.1. Exemple de config Caddy + +```bash +# /etc/caddy/Caddyfile + + { + encode gzip + + # Proxy API Headscale (port interne 8080) + reverse_proxy /api/* 127.0.0.1:8080 + + # UI headscale-admin statique + root * /var/www/headscale-admin + file_server +} +``` + +### 5.2. Points critiques + +- Le **serveur Headscale** écoute sur `:8080`. +- Le **reverse proxy** écoute en **:443** (et :80 pour HTTP → redirect vers 443). +- Les clients Tailscale **n’ont pas besoin du port** dans `--login-server` s’ils passent par HTTPS standard :`--login-server=https://` +- Si tu décides de garder un port non standard (`:8443` par ex.), **il faut le mettre partout** : + - dans `server_url` de Headscale ; + - dans `--login-server=` côté clients ; + - dans la config du reverse proxy. + +--- + +## 6. Gestion des utilisateurs et clés dans Headscale + +### 6.1. Créer un user + +```bash +headscale users create +headscale users list +``` + +Exemple : + +```bash +headscale users create syleric +``` + +### 6.2. Créer une preauth key + +```bash +headscale preauthkeys create --user --reusable --ephemeral=false +``` + +Exemple : + +```bash +headscale users list +# ID | Name | Username | Email | Created +# 1 | | $user | | ... + +headscale preauthkeys create --user 1 --reusable --ephemeral=false +# -> renvoie une clé du type : 548fd8... (ne pas mettre ici en clair) +``` + +> 🔁 Si tu doutes d’une clé, tu peux la **regénérer** et supprimer l’ancienne. + +--- + +## 7. Enregistrement des clients Tailscale + +### 7.1. Schéma global + +Pour chaque machine, on fait : + +```bash +tailscale logout || true +tailscale down || true + +tailscale up \ + --login-server=https:// \ + --auth-key= \ + --accept-dns=false \ + --accept-routes=false \ + --reset +``` + +> On utilise `--accept-dns=false` pour éviter que Headscale override le DNS local du homelab, +> et `--accept-routes=false` tant qu’on ne met pas en place de routes subnets poussées via Headscale. + +--- + +## 8. Cas particulier : macOS + +### 8.1. Utiliser le binaire Tailscale macOS + +Depuis le Mac : + +```bash +/Applications/Tailscale.app/Contents/MacOS/Tailscale status +/Applications/Tailscale.app/Contents/MacOS/Tailscale logout || true +/Applications/Tailscale.app/Contents/MacOS/Tailscale down || true +``` + +Puis : + +```bash +sudo /Applications/Tailscale.app/Contents/MacOS/Tailscale up \ + --login-server=https:// \ + --auth-key= \ + --accept-dns=false \ + --accept-routes=false \ + --reset +``` + +Si la clé est valide et le `--login-server` accessible, tu dois voir : + +```bash +/Applications/Tailscale.app/Contents/MacOS/Tailscale status +# 100.64.0.X macOS - +``` + +--- + +## 9. Cas particulier : Home Assistant (add-on Tailscale) + +### 9.1. Configurer l’add-on + +Dans la configuration de l’add-on Tailscale (interface Home Assistant) : + +```yaml +authkey: "" +hostname: "homeassistant" +login_server: "https://" +userspace_networking: true # ou false selon ton besoin +accept_dns: false +accept_routes: false +``` + +Ensuite, côté Headscale, tu verras un node : + +```bash +headscale nodes list +# ... +# homeassistant | homeassistant | ... | 100.64.0.9, ... +``` + +Si l’expiration a été mise par erreur, tu peux la corriger : + +```bash +headscale nodes expire --identifier --expiry 0001-01-01T00:00:00Z +``` + +> ⚠️ Attention : commande `expire` sert à **fixer** une date d’expiration. +> Pour ne pas expirer, il faut utiliser la valeur spéciale `0001-01-01T00:00:00Z`. + +--- + +## 10. Android (smartphone & tablette) + +### 10.1. Changer de serveur de login + +Sur Android, il n’y a **pas (encore)** de bouton clair dans l’UI pour changer de `login-server` vers un Headscale custom. + +La méthode fiable : + +1. **Se déconnecter** de Tailscale sur l’app (logout). +2. **Effacer les données** de l’appli (ou désinstaller/réinstaller) pour repartir de zéro. +3. Lors du premier `tailscale up` par CLI dans Termux (si tu utilises Termux + binaire Linux), lancer : + + ```bash + tailscale up \ + --login-server=https:// \ + --auth-key= \ + --accept-dns=false \ + --accept-routes=false \ + --reset + ``` +4. Côté Headscale, tu verras apparaître le nouveau node avec hostname (souvent `localhost` si tu utilises Termux) ; tu peux ensuite le renommer côté Headscale : + + ```bash + headscale nodes rename --identifier + ``` + +> 💡 Attention : renommer dans Headscale ne change pas le hostname système Android/Termux, mais ça rend la liste Headscale plus lisible. + +--- + +## 11. Vérifications globales + +### 11.1. Depuis Headscale + +```bash +headscale nodes list +``` + +Tu dois voir quelque chose du genre : + +```text +ID | Hostname | Name | IP addresses | Connected | Expired +1 | jenkins | jenkins | 100.64.0.1, fd7a:115c:a1e0::1 | online | no +2 | docker-ptr | docker-ptr | 100.64.0.2, fd7a:115c:a1e0::2 | online | no +3 | nas | nas | 100.64.0.5, fd7a:115c:a1e0::5 | online | no +... +``` + +### 11.2. Depuis un client (ex : PBS ou PVE) + +```bash +tailscale status +``` + +Tu dois voir **tous** les peers (Mac, Android, HA, etc.) avec leurs IPs `100.64.0.X`. + +--- + +## 12. Pièges rencontrés & leçons apprises + +### 12.1. Mauvais port dans le reverse proxy + +- **Symptôme :** + - `curl http://127.0.0.1:8080` → 404 ou rien + - Tailscale `up` semble bloquer ou ne jamais arriver à joindre le serveur +- **Cause :** + - Caddy/nginx servait sur le port `80`, mais on essayait d’appeler `:8080` depuis l’extérieur. +- **Solution :** + - Standardiser : + - Headscale API : `:8080` (interne) + - Reverse proxy : `:443` (public) + - `--login-server=https://` (pas de port explicite si 443) + +### 12.2. Mélange Tailscale SaaS / Headscale + +- **Symptôme :** + - Le client Tailscale ouvre une URL `https://login.tailscale.com/...` +- **Cause :** + - Pas de `--login-server` ou valeur incorrecte → le client repart sur le SaaS officiel. +- **Solution :** + - Toujours vérifier la commande `tailscale up` : + ```bash + tailscale up --login-server=https:// ... + ``` + +### 12.3. Expiration des nodes + +- **Symptôme :** + - Dans `headscale nodes list`, la colonne `Expired` passe à `yes`. +- **Cause :** + - Mauvaise manipulation de la commande `expire` avec une date proche du présent. +- **Solution :** + - Pour un node **qui ne doit pas expirer** : + ```bash + headscale nodes expire --identifier --expiry 0001-01-01T00:00:00Z + ``` + +--- + +## 13. Résumé rapide (mode pense‑bête) + +1. **Headscale** + + - Config dans `/etc/headscale/config.yaml` + - `listen_addr: 0.0.0.0:8080` + - `server_url: "https://"` +2. **Reverse proxy** + + - Terminate TLS (Let’s Encrypt) + - Proxy `/api` → `127.0.0.1:8080` + - Servir la Web UI statique (`/var/www/headscale-admin`) +3. **Utilisateur & clés** + + - `headscale users create ` + - `headscale preauthkeys create --user --reusable --ephemeral=false` +4. **Clients** + + - Commande type : + ```bash + tailscale logout || true + tailscale down || true + tailscale up \ + --login-server=https:// \ + --auth-key= \ + --accept-dns=false \ + --accept-routes=false \ + --reset + ``` +5. **Validation** + + - `headscale nodes list` + - `tailscale status` depuis plusieurs machines + +Avec cette checklist, tu peux **reconstruire tout ton tailnet Headscale** sans re‑te prendre 2 jours de galère, et tu peux publier ce README (après remplacement des placeholders) sur un dépôt public sans exposer ta vraie infra.