Files
Tailscale2Headscale/README.md
2025-12-14 22:38:07 +01:00

436 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 dutiliser ce document.
---
## 1. Objectif
Mettre en place un **contrôle Tailscale autohé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 :
- larchitecture 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 (Debianlike)
- Rôle : serveur `headscale` + Web UI (headscaleadmin)
- IP locale : `<HEADSCALE_LAN_IP>` (ex : `192.168.1.xxx`)
- Nom interne : `<HEADSCALE_HOSTNAME>` (ex : `headscale`)
- **Reverse proxy (facultatif mais recommandé)**
- Logiciel : `caddy` (ou nginx/traefik)
- Port HTTP interne Headscale : `8080`
- Port HTTPS public : `443`
- Nom de domaine : `<HEADSCALE_PUBLIC_FQDN>` (ex : `headscale.example.com`)
- Certificats : Lets Encrypt ou équivalent
- **Clients Tailscale**
- Serveur Proxmox VE : `<PVE_HOST>`
- Proxmox Backup Server : `<PBS_HOST>`
- NAS (OMV ou autre) : `<NAS_HOST>`
- Containers / VM : `<CT_DOCKER_PTR>`, `<CT_JENKINS>`, etc.
- Home Assistant : Add-on Tailscale
- macOS : client Tailscale officiel
- Android : app Tailscale officielle
Tout ce petit monde parle au **contrôle plane** : `https://<HEADSCALE_PUBLIC_FQDN>`.
---
## 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://<HEADSCALE_PUBLIC_FQDN>"
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 : headscaleadmin
### 4.1. Dossier et configuration
Headscaleadmin 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 à lAPI Headscale (port `8080` dans notre cas).
---
## 5. Reverse proxy (Caddy)
> Cest ici quon 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
<HEADSCALE_PUBLIC_FQDN> {
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 **nont pas besoin du port** dans `--login-server` sils passent par HTTPS standard :`--login-server=https://<HEADSCALE_PUBLIC_FQDN>`
- 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 <USERNAME>
headscale users list
```
Exemple :
```bash
headscale users create syleric
```
### 6.2. Créer une preauth key
```bash
headscale preauthkeys create --user <USER_ID> --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 dune clé, tu peux la **regénérer** et supprimer lancienne.
---
## 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://<HEADSCALE_PUBLIC_FQDN> \
--auth-key=<PREAUTH_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 quon 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://<HEADSCALE_PUBLIC_FQDN> \
--auth-key=<PREAUTH_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 <MAC_HOSTNAME> <USER> macOS -
```
---
## 9. Cas particulier : Home Assistant (add-on Tailscale)
### 9.1. Configurer ladd-on
Dans la configuration de ladd-on Tailscale (interface Home Assistant) :
```yaml
authkey: "<PREAUTH_KEY>"
hostname: "homeassistant"
login_server: "https://<HEADSCALE_PUBLIC_FQDN>"
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 lexpiration a été mise par erreur, tu peux la corriger :
```bash
headscale nodes expire --identifier <NODE_ID> --expiry 0001-01-01T00:00:00Z
```
> ⚠️ Attention : commande `expire` sert à **fixer** une date dexpiration.
> 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 ny a **pas (encore)** de bouton clair dans lUI pour changer de `login-server` vers un Headscale custom.
La méthode fiable :
1. **Se déconnecter** de Tailscale sur lapp (logout).
2. **Effacer les données** de lappli (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://<HEADSCALE_PUBLIC_FQDN> \
--auth-key=<PREAUTH_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 <NODE_ID> <NOM_SOUHAITÉ>
```
> 💡 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 dappeler `:8080` depuis lextérieur.
- **Solution :**
- Standardiser :
- Headscale API : `:8080` (interne)
- Reverse proxy : `:443` (public)
- `--login-server=https://<HEADSCALE_PUBLIC_FQDN>` (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://<HEADSCALE_PUBLIC_FQDN> ...
```
### 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 <ID> --expiry 0001-01-01T00:00:00Z
```
---
## 13. Résumé rapide (mode pensebête)
1. **Headscale**
- Config dans `/etc/headscale/config.yaml`
- `listen_addr: 0.0.0.0:8080`
- `server_url: "https://<HEADSCALE_PUBLIC_FQDN>"`
2. **Reverse proxy**
- Terminate TLS (Lets Encrypt)
- Proxy `/api` → `127.0.0.1:8080`
- Servir la Web UI statique (`/var/www/headscale-admin`)
3. **Utilisateur & clés**
- `headscale users create <USERNAME>`
- `headscale preauthkeys create --user <ID> --reusable --ephemeral=false`
4. **Clients**
- Commande type :
```bash
tailscale logout || true
tailscale down || true
tailscale up \
--login-server=https://<HEADSCALE_PUBLIC_FQDN> \
--auth-key=<PREAUTH_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 rete 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.