📍 Article principal de la série : Headscale 2026 : guide complet.
Vos applications internes (back-office, dashboards, services métier) n’ont aucune raison d’être exposées sur Internet public. En combinant Headscale (mesh VPN auto-hébergé) et Coolify (PaaS open source), vous obtenez une plateforme de déploiement où chaque app est accessible uniquement aux membres de votre tailnet. Aucune URL publique, aucune attaque DDoS possible, conformité maximale.
Prérequis
- Headscale en production avec ACL configurées.
- Coolify v4 installé sur un VPS (voir Guide Coolify).
- Au moins un client Tailscale connecté côté équipe.
- Niveau attendu : avancé.
- Temps estimé : 2 à 3 heures.
Étape 1 — Architecture cible
Schéma : utilisateur (laptop avec Tailscale) → mesh Headscale → VPS Coolify (Tailscale installé) → applications déployées (chacune écoute uniquement sur l’IP Tailscale).
Aucun port 80/443 du VPS Coolify n’est exposé sur l’IP publique. Le firewall UFW bloque tout entrant sauf 22 (SSH) et UDP 41641 (Tailscale).
Étape 2 — Connecter le VPS Coolify à Headscale
Sur le VPS Coolify :
curl -fsSL https://tailscale.com/install.sh | sh
PREAUTH=$(headscale preauthkeys create -u servers --expiration 720h)
tailscale up --login-server=https://headscale.votre-entreprise.com \
--auth-key=$PREAUTH \
--advertise-tags=tag:coolify,tag:server-prod \
--ssh
tailscale ip -4
# Note l'IP attribuée, par exemple 100.64.0.5
Étape 3 — Configurer Coolify pour bind sur l’IP Tailscale
Coolify expose son interface admin sur le port 8000 par défaut. Restreindre :
# Edit /data/coolify/source/.env
APP_URL=https://coolify-tail.tailnet.ts.net
SSL_MODE=off # On gère HTTPS via Caddy interne
Configurer Caddy interne de Coolify pour servir uniquement sur l’IP Tailscale :
coolify-tail.tailnet.ts.net:80 {
bind 100.64.0.5
reverse_proxy localhost:8000
}
Bloquer toutes les autres connexions :
ufw default deny incoming
ufw allow 22/tcp
ufw allow 41641/udp
ufw enable
Étape 4 — Déployer une application interne
Dans Coolify, déployer une app standard (Next.js, Hono, Astro). Dans la section Domains, au lieu d’un domaine public, mettre :
https://outline.tailnet.ts.net
Coolify génère un certificat Let’s Encrypt via DNS-01 (cert manager) pour le sous-domaine MagicDNS. Le service écoute sur l’IP Tailscale uniquement.
Étape 5 — Configurer MagicDNS Headscale
Dans /etc/headscale/config.yaml :
dns:
magic_dns: true
base_domain: tailnet.ts.net
override_local_dns: true
nameservers:
global:
- 1.1.1.1
Restart : systemctl restart headscale. Tous les clients Tailscale réauthentifiés résolvent désormais nom-machine.tailnet.ts.net automatiquement.
Étape 6 — ACL pour accès aux apps
Compléter /etc/headscale/policy.hujson :
{
"acls": [
{
"action": "accept",
"src": ["group:devs", "group:marketing"],
"dst": ["tag:coolify:443"]
}
]
}
Étape 7 — Test depuis un client
Sur le laptop d’un développeur connecté au tailnet :
tailscale ping coolify-tail
# Doit répondre direct ou via DERP
curl https://outline.tailnet.ts.net
# Doit retourner la home Outline
Ouvrir le navigateur sur https://outline.tailnet.ts.net : l’app charge. Sur un appareil non connecté au tailnet : connexion refusée (timeout). Sécurité maximale.
Étape 8 — Apps multi-utilisateurs
Pour Vaultwarden, Forgejo, Outline, Grafana, Plausible : déployer chacun comme app Coolify standard avec domaine MagicDNS dédié. Toutes héritent du contrôle d’accès Headscale.
Étape 9 — Backups et failover
Conserver un domaine public de fallback pour Coolify lui-même : coolify.votre-entreprise.com sur l’IP publique avec UFW restreint à votre IP admin uniquement. En cas de panne Headscale, vous gardez l’accès au panel admin.
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| App inaccessible depuis tailnet | Coolify écoute sur 0.0.0.0 mais firewall bloque | Bind explicite sur IP Tailscale |
| Let’s Encrypt échoue sur tailnet | HTTP-01 challenge impossible sans IP publique | DNS-01 via Cloudflare API ou cert auto-signé interne |
| MagicDNS ne résout pas | Client Tailscale pas redémarré | tailscale down && tailscale up |
| Performance dégradée | Pas de DERP régional | Configurer DERP en Europe ou Afrique |
| SSH inaccessible si Headscale down | UFW bloque 22 par défaut | Garder règle UFW allow 22 from votre-ip-admin |
| Coolify déploie mais services ne tournent pas | Containers en network bridge sans accès tailnet | Configurer containers en network host |
Adaptation au contexte ouest-africain
Trois précisions. Bande passante : pour 30 employés accédant aux apps internes, comptez 5 Mb/s sortant agrégé. Hetzner CX22 offre 1 Gb/s, largement suffisant. Coût total : Headscale (4,51 €) + Coolify (3,99 €) + nom de domaine (12 €/an) = ~ 100 € la première année. Conformité : architecture parfaitement compatible RGPD, ARTCI, NESA. Aucune donnée ne quitte les serveurs européens, aucun service public n’est exposé.
Tutoriels frères
FAQ
Pourquoi pas Tailscale Funnel pour exposer publiquement ? Funnel est une feature Tailscale Cloud uniquement, pas Headscale. Pour exposer publiquement, garder un Caddy classique avec domaine public.
Comment monitorer la disponibilité des apps internes ? Uptime Kuma déployé dans Coolify, accessible via tailnet, monitore les autres apps via leurs URLs MagicDNS.
Mobile : comment accéder aux apps depuis téléphone ? App Tailscale officielle, MagicDNS activé, taper l’URL outline.tailnet.ts.net dans Safari/Chrome.
Que faire si Headscale tombe ? Coolify reste accessible via SSH. Apps inaccessibles tant que Headscale ne redémarre pas. Plan de rollback : exposer temporairement Coolify avec UFW + cert.
Cette architecture passe-t-elle un audit SOC2 ? Avec logs Loki + monitoring + ACL documentées, oui. C’est une architecture Zero Trust standard.
Pour aller plus loin
- 🔝 Retour au guide général : Guide complet Headscale 2026
- Documentation Coolify : coolify.io/docs