Add new post on VPN
Tim Izzo tim@5ika.ch
Tue, 05 May 2026 21:38:20 +0200
1 files changed,
129 insertions(+),
0 deletions(-)
jump to
A
content/posts/un-vpn-facile.md
@@ -0,0 +1,129 @@
+--- +Title: Mettre en place un VPN facilement +Date: 2026-05-05 +--- + +Pour mon entreprise, je gère un ensemble de serveurs hébergeant nos outils internes, nos instances de test ainsi que certaines instances de production. +C'est un job à plein temps que de gérer ces serveurs et, comme la plupart des services n'ont pas énormément d'utilisateurs, c'est souvent exagérément long de mettre en place des points d'accès sécurisés voir de faire les configurations minimales. + +L'an passé, j'ai passé pas mal d'heures à configurer des interfaces [Wireguard](https://www.wireguard.com/) sur chaque serveur. J'adore Wireguard pour son côté minimal et bas niveau mais avec le nombre de serveurs et d'utilisateurs augmentant, ça devient rapidement galère de gérer les configs sur chaque serveur. + +Après quelques recherches, je suis tombé sur [Tailscale](https://tailscale.com/) et son alter-ego Open-Source auto-hébergeable [Headscale](https://headscale.net/). Ce système repose sur Wireguard mais s'occupe de toute la partie config redondante tout en ajoutant des fonctionnalités supplémentaires: DNS automatique des nodes connectés, gestion facilité du SSH, règles ACL, file sharing et [d'autres encores](https://headscale.net/stable/about/features/). + +Cependant, la doc de Headscale est plutôt limitée et celle de Tailscale me perd rapidement. Je profite donc de cet article pour documenter les quelques étapes utiles pour mettre en place un réseau privé Open-Source en 10 minutes. + +## Mise en place du control plane + +Headscale est à installer sur un serveur accessible en ligne. +Soit [directement sur la machine](https://headscale.net/stable/setup/install/official/#using-standalone-binaries-advanced), soit en utilisant un [container Docker](https://headscale.net/stable/setup/install/container/). + +Pour la méthode Docker, le programme `headscale` doit être lancé avec la commande suivante: + +```bash +docker exec -it headscale headscale +``` + +Ce qui n'est pas très pratique donc je préfère ajouter un alias au niveau de Bash: + +```bash +alias headscale=`docker exec -it headscale headscale` +``` + +De mon côté, j'utilise généralement Docker Compose avec une auto-config Traefik: + +```yaml +services: + headscale: + image: headscale/headscale:stable + container_name: headscale + restart: unless-stopped + volumes: + - ./config:/etc/headscale:ro + - ./lib:/var/lib/headscale + command: serve + healthcheck: + test: ["CMD", "headscale", "health"] + interval: 10s + timeout: 5s + retries: 3 + labels: + - traefik.enable=true + - traefik.http.routers.headscale.rule=Host(`headscale.myhost.ch`) + - traefik.http.routers.headscale.entrypoints=websecure + - traefik.http.services.headscale.loadbalancer.server.port=8080 + - traefik.http.routers.headscale.tls=true + - traefik.http.routers.headscale.tls.certresolver=letsencrypt +``` + +Ensuite, on récupère la base de configuration et on l'édite. Elle est bien documentée et facile à adapter. + +```bash +wget -O config/config.yaml https://github.com/juanfont/headscale/blob/main/config-example.yaml +$EDITOR config/config.yaml +``` + +Afin de configuer les ACL, il faut notamment modifier les lignes `policy.path` pour adapter comme suit: + +```yaml +policy: + path: "/etc/headscale/acl.hujson" +``` + +Et on crée le fichier `acl.hujson` dans le dossier `config/` avec le contenu suivant (à adapter selon les besoins): + +```json +{ + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:*"] + } + ], + "ssh": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:member"], + "users": ["root"] + } + ] +} +``` + +Pour plus d'infos sur la configuration des ACLs, [voir la doc de Tailscale](https://tailscale.com/docs/features/access-control/acls). + +Ensuite, on (re)démarre Headscale pour appliquer la nouvelle configuration. Avec Docker Compose: `docker compose up -d`. + +## Configuration du client + +1. Sur chaque node que l'on veut connecter au VPN, on installe [Tailscale CLI](https://tailscale.com/docs/reference/tailscale-cli). +2. Sur le serveur, on crée un utilisateur +```bash +headscale users create <user> +``` +3. On génère une *PreAuthKey* pour cette utilisateur +```bash +headscale preauthkeys create --user <user> +``` +4. Sur la machine cliente, on se connecte en utilisant la PreAuthKey +```bash +tailscale up --login-server https://headscale.myhost.ch --authkey <preAuthKey> +``` + +Pour tester que l'on obtient bien une IP dans le VPN: + +```bash +tailscale status +``` + +Une fois que nous avons au moins deux nodes dans le réseau, on peut faire un ping entre les deux pour tester le lien. Grâce au [MagicDNS](https://tailscale.com/docs/features/magicdns) fourni par Headscale, on peut utiliser le hostname de chaque client pour le contacter. +Par exemple, si un client est connecté avec une machine dans le hostname est `deer`, on peut faire `ping deer` depuis un autre node pour l'atteindre. + +## Notes de fin + +Ces quelques commandes permettent de créer rapidement un réseau DNS. Je passe sur les configurations nécessaires pour rendre accessible le Headscale depuis le Web car cela dépend fortement du cas d'usage. L'utilisation de Traefik Proxy ou d'un Caddy server rend ça plutôt simple. + +Dès que l'on fait grandir le réseau, il devient assez vite nécessaire de mettre en place des ACL un peu réfléchies. + +Pour voir toutes les possibilités offertes, [cette page](https://headscale.net/stable/about/features/) est une bonne référence.