Update README.md
This commit is contained in:
436
README.md
436
README.md
@@ -1 +1,435 @@
|
||||
# Tailscale2Headscale
|
||||
# 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 : `<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 : Let’s 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 : 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
|
||||
|
||||
<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 **n’ont pas besoin du port** dans `--login-server` s’ils 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 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://<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 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://<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 l’add-on
|
||||
|
||||
Dans la configuration de l’add-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 l’expiration 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 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://<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 d’appeler `:8080` depuis l’exté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 pense‑bê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 (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 <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 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.
|
||||
|
||||
Reference in New Issue
Block a user