Headscale
Ce guide vous explique comment configurer l'authentification unique (SSO) entre SmartLink et Headscale en utilisant OpenID Connect. Headscale est une implémentation open-source du serveur de contrôle Tailscale.
Prérequis
- Headscale version 0.22.0 ou supérieure
- Accès administrateur au serveur Headscale
- Application configurée dans SmartLink avec OpenID Connect
- Certificat SSL valide pour Headscale (requis pour OIDC)
Vue d'ensemble
Headscale supporte l'authentification via OpenID Connect, permettant aux utilisateurs de s'authentifier avec SmartLink au lieu de pré-générer des clés d'authentification.
Configuration dans SmartLink
1. Créer l'application
- Connectez-vous à SmartLink en tant qu'administrateur
- Allez dans Applications → Ajouter
- Créez une nouvelle application :
- Nom : Headscale
- URL :
https://headscale.example.com - Description : Serveur de contrôle Headscale
- Icône : Utilisez l'icône Tailscale ou une icône personnalisée
2. Configurer OpenID Connect
- Dans l'onglet Authentification
- Sélectionnez OpenID Connect comme type d'authentification
- Notez les informations suivantes :
- Client ID :
headscale-xxxxxx - Client Secret :
secret-xxxxxx - Issuer URL :
https://votre-smartlink.link.vaultys.org/api/oidc/[appid] - App ID :
[appid](identifiant unique de l'application dans SmartLink)
- Client ID :
3. Configurer les URLs de redirection
Ajoutez l'URL de callback dans URLs de redirection autorisées :
https://headscale.example.com/oidc/callback
Note: L'
[appid]sera automatiquement généré lors de la création de l'application dans SmartLink.
4. Configurer les scopes
Scopes requis :
openidprofileemailgroups(optionnel, pour les ACLs basées sur les groupes)
Configuration de Headscale
1. Configuration du fichier config.yaml
Éditez le fichier de configuration Headscale (généralement /etc/headscale/config.yaml) :
# Configuration du serveur
server_url: https://headscale.example.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
# Configuration de la base de données
db_type: sqlite3
db_path: /var/lib/headscale/db.sqlite
# Configuration OIDC
oidc:
# Activer OIDC
enabled: true
# URL de l'issuer SmartLink
issuer: "https://votre-smartlink.link.vaultys.org/api/oidc/[appid]"
# Client ID et Secret depuis SmartLink
client_id: "headscale-xxxxxx"
client_secret: "secret-xxxxxx"
# Scopes à demander
scope:
- openid
- profile
- email
- groups
# Claims pour mapper les informations utilisateur
claims:
# Claim pour l'email (identifiant utilisateur)
email: email
# Claim pour le nom d'affichage
name: name
# Claim pour les groupes (optionnel)
groups: groups
# Domaines email autorisés
allowed_domains:
- example.com
# Groupes autorisés (optionnel)
allowed_groups:
- admins
- developers
- users
# Créer automatiquement les utilisateurs
auto_create_users: true
# Durée de vie du token d'authentification
expiry: 180d
# Utiliser l'expiration du token OIDC
use_expiry_from_token: false
# Configuration des namespaces/users
ip_prefixes:
- 100.64.0.0/10
- fd7a:115c:a1e0::/48
# Configuration DNS
dns_config:
nameservers:
- 1.1.1.1
- 8.8.8.8
domains: []
magic_dns: true
base_domain: example.com
2. Configuration avec variables d'environnement
Alternativement, vous pouvez utiliser des variables d'environnement :
export HEADSCALE_OIDC_ENABLED=true
export HEADSCALE_OIDC_ISSUER="https://votre-smartlink.link.vaultys.org"
export HEADSCALE_OIDC_CLIENT_ID="headscale-xxxxxx"
export HEADSCALE_OIDC_CLIENT_SECRET="secret-xxxxxx"
export HEADSCALE_OIDC_ALLOWED_DOMAINS="example.com"
3. Démarrage avec Docker
Si vous utilisez Docker, voici un exemple de docker-compose.yml :
version: '3.8'
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
volumes:
- ./config:/etc/headscale
- ./data:/var/lib/headscale
ports:
- "8080:8080"
- "9090:9090"
environment:
- HEADSCALE_OIDC_ENABLED=true
- HEADSCALE_OIDC_ISSUER=https://votre-smartlink.link.vaultys.org
- HEADSCALE_OIDC_CLIENT_ID=headscale-xxxxxx
- HEADSCALE_OIDC_CLIENT_SECRET=secret-xxxxxx
command: headscale serve
restart: unless-stopped
4. Configuration du reverse proxy (Nginx)
Exemple de configuration Nginx pour Headscale avec SSL :
server {
listen 443 ssl http2;
server_name headscale.example.com;
ssl_certificate /etc/letsencrypt/live/headscale.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/headscale.example.com/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect http:// https://;
proxy_buffering off;
}
}
Configuration des ACLs avec groupes
1. Structure des ACLs basées sur les groupes
Créez un fichier acls.yaml ou acls.hujson :
groups:
group:admins:
- user1@example.com
group:developers:
- user2@example.com
acls:
- action: accept
src:
- group:admins
dst:
- "*:*"
- action: accept
src:
- group:developers
dst:
- tag:dev:*
- tag:staging:*
tagOwners:
tag:prod:
- group:admins
tag:dev:
- group:developers
tag:staging:
- group:developers
2. Application des ACLs
# Appliquer les ACLs
headscale acls set acls.yaml
# Vérifier les ACLs
headscale acls show
Configuration du client
1. Installation du client Tailscale
# Linux
curl -fsSL https://tailscale.com/install.sh | sh
# macOS
brew install tailscale
# Windows
# Téléchargez depuis https://tailscale.com/download
2. Connexion avec OIDC
# Connexion au serveur Headscale avec OIDC
tailscale up --login-server https://headscale.example.com
# Le navigateur s'ouvre automatiquement pour l'authentification
# Vous serez redirigé vers SmartLink pour vous connecter
3. Vérification de la connexion
# Vérifier le statut
tailscale status
# Voir les pairs connectés
tailscale status --peers
# Vérifier l'IP assignée
tailscale ip
Test de la configuration
1. Test de l'authentification OIDC
- Sur un client, exécutez :
tailscale up --login-server https://headscale.example.com - Le navigateur s'ouvre sur la page d'authentification
- Cliquez sur "Login with OIDC"
- Vous êtes redirigé vers SmartLink
- Connectez-vous avec vos identifiants SmartLink
- Après authentification, vous êtes redirigé vers Headscale
- Le client Tailscale devrait se connecter automatiquement
2. Vérification dans Headscale
# Lister les utilisateurs
headscale users list
# Lister les machines
headscale machines list
# Voir les détails d'un utilisateur
headscale users show utilisateur@example.com
# Voir les routes
headscale routes list
3. Test de connectivité
# Ping d'une autre machine
ping 100.64.0.2
# Test avec hostname MagicDNS
ping machine-name.example.com.beta.tailscale.net
Dépannage
Erreur "OIDC authentication failed"
Problème : L'authentification OIDC échoue
Solution :
- Vérifiez les logs Headscale :
journalctl -u headscale -f - Vérifiez l'URL de l'issuer dans la config
- Testez la découverte OIDC avec votre appid :
curl https://votre-smartlink.link.vaultys.org/api/oidc/[appid]/.well-known/openid-configuration
Erreur "Invalid client credentials"
Problème : Les credentials OIDC sont invalides
Solution :
- Vérifiez le Client ID et Secret dans SmartLink
- Assurez-vous qu'il n'y a pas d'espaces ou de caractères cachés
- Redémarrez Headscale après modification de la config
L'utilisateur est créé mais ne peut pas se connecter
Problème : L'utilisateur existe dans Headscale mais la connexion échoue
Solution :
- Vérifiez que le domaine email est dans
allowed_domains - Si vous utilisez
allowed_groups, vérifiez les groupes de l'utilisateur - Vérifiez les ACLs si configurées
- Essayez de réauthentifier l'utilisateur :
headscale preauthkeys create --user utilisateur@example.com
Les groupes ne sont pas synchronisés
Problème : Les groupes SmartLink ne sont pas visibles dans Headscale
Solution :
- Vérifiez que le scope
groupsest activé dans SmartLink - Testez l'endpoint UserInfo :
curl -H "Authorization: Bearer TOKEN" https://votre-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo - Vérifiez le claim des groupes dans la config Headscale
- Les groupes doivent être un array de strings
Erreur SSL/TLS
Problème : Erreur de certificat lors de la connexion OIDC
Solution :
- Headscale requiert HTTPS avec un certificat valide
- N'utilisez pas de certificats auto-signés
- Vérifiez la chaîne de certificats :
openssl s_client -connect headscale.example.com:443 -showcerts
Sécurité
Recommandations
- HTTPS obligatoire : Headscale requiert HTTPS pour OIDC
- Firewall : Limitez l'accès au port Headscale (8080)
- Base de données : Utilisez PostgreSQL en production
- Secrets : Stockez les secrets de manière sécurisée
- Monitoring : Surveillez les logs et métriques
Rotation des clés
# Générer une nouvelle clé de nœud
headscale nodes key rotate --id NODE_ID
# Révoquer une machine
headscale machines delete --id MACHINE_ID
Sauvegarde
# Sauvegarder la base de données SQLite
sqlite3 /var/lib/headscale/db.sqlite ".backup /backup/headscale.db"
# Sauvegarder la configuration
cp -r /etc/headscale /backup/headscale-config
# Avec PostgreSQL
pg_dump headscale > /backup/headscale.sql
Configuration avancée
Mode multi-utilisateur avec namespaces
# Dans config.yaml
oidc:
# Créer un namespace par utilisateur
create_namespace_for_user: true
# Format du namespace
namespace_format: "{email}"
# Ou utiliser un claim spécifique
namespace_claim: "department"
Intégration avec Kubernetes
Déploiement Headscale dans Kubernetes :
apiVersion: apps/v1
kind: Deployment
metadata:
name: headscale
spec:
replicas: 1
selector:
matchLabels:
app: headscale
template:
metadata:
labels:
app: headscale
spec:
containers:
- name: headscale
image: headscale/headscale:latest
ports:
- containerPort: 8080
env:
- name: HEADSCALE_OIDC_ENABLED
value: "true"
- name: HEADSCALE_OIDC_ISSUER
value: "https://votre-smartlink.example.com"
- name: HEADSCALE_OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: headscale-oidc
key: client-id
- name: HEADSCALE_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: headscale-oidc
key: client-secret
volumeMounts:
- name: config
mountPath: /etc/headscale
- name: data
mountPath: /var/lib/headscale
volumes:
- name: config
configMap:
name: headscale-config
- name: data
persistentVolumeClaim:
claimName: headscale-data
Monitoring avec Prometheus
Headscale expose des métriques sur le port 9090 :
# prometheus.yml
scrape_configs:
- job_name: 'headscale'
static_configs:
- targets: ['headscale.example.com:9090']