Skip to main content

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.

1. Créer l'application

  1. Connectez-vous à SmartLink en tant qu'administrateur
  2. Allez dans ApplicationsAjouter
  3. 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

  1. Dans l'onglet Authentification
  2. Sélectionnez OpenID Connect comme type d'authentification
  3. 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)

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 :

  • openid
  • profile
  • email
  • groups (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

  1. Sur un client, exécutez :
    tailscale up --login-server https://headscale.example.com
  2. Le navigateur s'ouvre sur la page d'authentification
  3. Cliquez sur "Login with OIDC"
  4. Vous êtes redirigé vers SmartLink
  5. Connectez-vous avec vos identifiants SmartLink
  6. Après authentification, vous êtes redirigé vers Headscale
  7. 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 :

  1. Vérifiez les logs Headscale :
    journalctl -u headscale -f
  2. Vérifiez l'URL de l'issuer dans la config
  3. 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 :

  1. Vérifiez le Client ID et Secret dans SmartLink
  2. Assurez-vous qu'il n'y a pas d'espaces ou de caractères cachés
  3. 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 :

  1. Vérifiez que le domaine email est dans allowed_domains
  2. Si vous utilisez allowed_groups, vérifiez les groupes de l'utilisateur
  3. Vérifiez les ACLs si configurées
  4. 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 :

  1. Vérifiez que le scope groups est activé dans SmartLink
  2. Testez l'endpoint UserInfo :
    curl -H "Authorization: Bearer TOKEN" https://votre-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo
  3. Vérifiez le claim des groupes dans la config Headscale
  4. Les groupes doivent être un array de strings

Erreur SSL/TLS

Problème : Erreur de certificat lors de la connexion OIDC

Solution :

  1. Headscale requiert HTTPS avec un certificat valide
  2. N'utilisez pas de certificats auto-signés
  3. Vérifiez la chaîne de certificats :
    openssl s_client -connect headscale.example.com:443 -showcerts

Sécurité

Recommandations

  1. HTTPS obligatoire : Headscale requiert HTTPS pour OIDC
  2. Firewall : Limitez l'accès au port Headscale (8080)
  3. Base de données : Utilisez PostgreSQL en production
  4. Secrets : Stockez les secrets de manière sécurisée
  5. 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']

Ressources