📍 Article principal du cluster : Headscale 2026 : guide complet.
Sans ACL, votre Headscale est un réseau plat où chaque appareil peut joindre chaque autre sur tous les ports. Pour une équipe de 30 personnes répartie entre Dakar, Abidjan et Casablanca, c’est un anti-pattern de sécurité majeur. Ce tutoriel détaille la mise en place de politiques HuJSON robustes : utilisateurs, groupes, tags, autorisations granulaires, exemples copier-coller.
Prérequis
- Headscale en production (voir tutoriel d’installation).
- Au moins 5 appareils enregistrés.
- Notion de RBAC (Role-Based Access Control).
- Niveau attendu : intermédiaire/avancé.
- Temps estimé : 2 à 3 heures.
Étape 1 — Comprendre la structure HuJSON
Une politique Headscale comporte cinq sections principales :
groups: groupes d’utilisateurs (équivalents groupes RBAC).tagOwners: qui peut assigner quels tags.autoApprovers: routes et exit nodes pré-approuvés.acls: règles d’autorisation effectives.ssh: règles spécifiques SSH (Tailscale SSH).
Étape 2 — Définir les utilisateurs et groupes
Dans /etc/headscale/policy.hujson :
{
"groups": {
"group:admins": ["amadou@votre-entreprise.com"],
"group:devs": ["amadou@...", "fatou@...", "ousmane@..."],
"group:marketing": ["aicha@...", "moussa@..."],
"group:finance": ["khadija@..."],
"group:freelances": ["consultant1@external.com"]
},
"tagOwners": {
"tag:server-prod": ["group:admins"],
"tag:server-staging": ["group:devs"],
"tag:database-prod": ["group:admins"],
"tag:office-dakar": ["group:admins"]
}
}
Étape 3 — Définir les ACL principales
"acls": [
// Admins ont accès total
{
"action": "accept",
"src": ["group:admins"],
"dst": ["*:*"]
},
// Développeurs : SSH sur staging et prod, accès apps internes
{
"action": "accept",
"src": ["group:devs"],
"dst": ["tag:server-staging:22,80,443,5432,6379"]
},
{
"action": "accept",
"src": ["group:devs"],
"dst": ["tag:server-prod:443"]
},
// Marketing : accès à Vaultwarden, Outline, Plausible uniquement
{
"action": "accept",
"src": ["group:marketing"],
"dst": ["100.64.0.10:443", "100.64.0.11:443", "100.64.0.12:443"]
},
// Finance : accès ERP uniquement
{
"action": "accept",
"src": ["group:finance"],
"dst": ["100.64.0.20:443"]
},
// Freelances : staging seulement, expire automatiquement
{
"action": "accept",
"src": ["group:freelances"],
"dst": ["tag:server-staging:80,443"]
},
// Subnet routers : autorisation pour LAN bureau Dakar
{
"action": "accept",
"src": ["group:devs", "group:admins"],
"dst": ["192.168.10.0/24:*"]
}
]
Étape 4 — SSH avec Tailscale SSH
Tailscale SSH (et Headscale SSH) permet de SSH sans clé publique, l’authentification étant gérée par le mesh :
"ssh": [
// Admins peuvent SSH partout en root
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server-prod", "tag:server-staging"],
"users": ["root", "ubuntu", "debian"]
},
// Devs peuvent SSH sur staging avec leur propre user
{
"action": "accept",
"src": ["group:devs"],
"dst": ["tag:server-staging"],
"users": ["autogroup:nonroot"]
},
// Devs peuvent SSH sur prod uniquement avec check 2FA (futur)
{
"action": "check",
"src": ["group:devs"],
"dst": ["tag:server-prod"],
"users": ["autogroup:nonroot"],
"checkPeriod": "1h"
}
]
Étape 5 — Tester la politique avant application
headscale policy check -f /etc/headscale/policy.hujson
# Retourne : Policy is valid
headscale policy set -f /etc/headscale/policy.hujson
# Retourne : Policy applied successfully
Étape 6 — Assigner les tags aux serveurs
Sur le serveur Postgres production :
tailscale up --login-server=https://headscale.votre-entreprise.com \
--auth-key=PREAUTH \
--advertise-tags=tag:server-prod,tag:database-prod
Côté Headscale, approuver l’attribution :
headscale nodes tag -i ID_DU_NODE -t tag:server-prod,tag:database-prod
Étape 7 — Audit et conformité
Toutes les actions Headscale sont loggées. Pour un audit mensuel :
journalctl -u headscale --since "1 month ago" | grep -i "policy\|tag\|register"
Pour une PME soumise à RGPD ou ARTCI, exporter ces logs vers Loki + Grafana avec rétention 1 an minimum.
Cas spécial : équipe multi-sites
Pour une équipe répartie sur 3 villes (Dakar, Abidjan, Casablanca), définir des tags géographiques permet d’écrire des règles type « les devs Dakar peuvent SSH les serveurs Dakar, idem Abidjan » :
"groups": {
"group:devs-dakar": [...],
"group:devs-abidjan": [...],
"group:devs-casa": [...]
},
"tagOwners": {
"tag:server-dakar": ["group:devs-dakar"],
"tag:server-abidjan": ["group:devs-abidjan"],
"tag:server-casa": ["group:devs-casa"]
},
"acls": [
{"action": "accept", "src": ["group:devs-dakar"], "dst": ["tag:server-dakar:*"]},
{"action": "accept", "src": ["group:devs-abidjan"], "dst": ["tag:server-abidjan:*"]},
// Sauf admins, qui ont tout
{"action": "accept", "src": ["group:admins"], "dst": ["*:*"]}
]
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| Politique vide bloque tout | Pas de règle accept par défaut | Ajouter règle {"action":"accept","src":["*"],"dst":["*:*"]} au début pour tester |
| Erreur HuJSON syntaxe | Virgule manquante | headscale policy check indique la ligne |
| Tag refusé | tagOwners absent | Ajouter le tag dans tagOwners |
| Freelance toujours connecté | Compte non supprimé | headscale users destroy nom |
| SSH par tag refusé | tag non assigné côté server | Vérifier tailscale status sur le serveur |
| Updates ne propagent pas | Cache client | Forcer reconnect : tailscale set --auto-update |
Adaptation au contexte ouest-africain
Trois ajustements concrets. Freelances et stagiaires : très fréquents en Afrique, créer un groupe dédié group:temporaires avec ACL strictes (staging only, ports limités, SSH read-only). Suppression auto possible via cron : headscale users destroy temporaire-X après 30 jours d’inactivité. Sites distribués : pour un cabinet d’avocats à Casablanca/Tanger/Marrakech, tagger chaque site permet d’isoler les ressources locales. Conformité ARTCI : exiger les ACL en lecture/écriture sur les serveurs production uniquement pour les comptes traçables (pas de compte partagé).
Tutoriels frères
FAQ
Combien de règles ACL Headscale supporte-t-il ? Plusieurs centaines sans impact perceptible. Les tests Tailscale ont validé jusqu’à 10 000 règles.
Comment auditer qui a accédé à quoi ? Logs Headscale + logs SSH côté serveurs (auditd ou rsyslog). Croiser les deux donne une trace complète.
Politique HuJSON Tailscale Cloud compatible ? 95% oui. Quelques différences sur SSH check mode et certaines features Enterprise non supportées.
Que faire en cas d’erreur de politique en prod ? Garder une politique « safe rollback » testée dans Git. headscale policy set -f safe.hujson rétablit l’ancien état en 5 secondes.
Comment imposer un check 2FA pour SSH prod ? Mode "action": "check" avec checkPeriod. À la première session SSH, l’utilisateur doit confirmer via app mobile ou clé matérielle.
Pour aller plus loin
- 🔝 Retour au pilier : Guide complet Headscale 2026
- Documentation HuJSON Tailscale : tailscale.com/kb/1018/acls