Tutoriel · Souveraineté Numérique
VPN Souverain
avec Headscale
Un tunnel WireGuard que toi seul administres, hébergé dans la juridiction de ton choix. Pas de tiers. Pas de logs. Pas de dépendance.
Tutorial · Digital Sovereignty
Sovereign VPN
with Headscale
A WireGuard tunnel that only you control, hosted in the jurisdiction of your choice. No third party. No logs. No dependency.
Ce qu'il te faut avant de commencer
- Un VPS Ubuntu 22.04 (Infomaniak, 1984 Hosting ou UpCloud), budget ~10€/mois
- Docker + Docker Compose installés sur le VPS
- Un nom de domaine avec accès DNS (ex:
vpn.tondomaine.io) - Un terminal : macOS Terminal, Linux Terminal ou Windows WSL2
What you need before starting
- An Ubuntu 22.04 VPS (Infomaniak, 1984 Hosting, or UpCloud), budget ~€10/month
- Docker + Docker Compose installed on the VPS
- A domain name with DNS access (e.g.:
vpn.yourdomain.io) - A terminal: macOS Terminal, Linux Terminal, or Windows WSL2
★ Intermédiaire technique = tu as déjà lancé un docker run et utilisé un terminal SSH. Débutant souveraineté = tu n'as jamais configuré de VPN, c'est normal et attendu.
★ Intermediate technical = you've run docker run and used an SSH terminal before. Beginner sovereignty = you've never set up a VPN, that's expected and fine.
Before you start
5 minChapter objective
You know exactly what you're going to build, how much it costs, and what the final result will look like. Zero surprises.
Quick test, 5 minutes, zero cost, no VPS needed
Before renting a server, verify that Docker is ready on your machine and the Headscale image is accessible. One command, instant result:
# Run this command on YOUR machine (not the VPS) docker run --rm headscale/headscale:latest headscale version headscale v0.23.0 ← you should see a version here # If you see a version → Docker is ready, let's continue. # Otherwise: # "docker: command not found" → install Docker Desktop # "Cannot connect to the Docker daemon" → start Docker Desktop
Enter your values as you go: every command in the tutorial is rewritten with them, and the "Copy" button will copy YOUR version. Stored only in your browser (localStorage), never sent anywhere.
Personalized values appear highlighted like this in the commands.
By the end of this tutorial, you'll have a WireGuard private network managed by Headscale, an open source software running on your server. Your devices (computer, phone, other servers) will communicate via this encrypted network, without going through any third-party service.
What you'll build
# Your private network at the end of the tutorial Your VPS (e.g.: 89.145.x.x) Your local machine ┌─────────────────────────┐ ┌──────────────────────┐ │ Headscale : 100.64.0.1 │◄──────│ Client : 100.64.0.2 │ │ Port 443 (public HTTPS)│ VPN │ No open ports │ │ Port 51820 (WireGuard) │ ───► │ Outbound connection │ └─────────────────────────┘ └──────────────────────┘ ↑ Internet visible to anyone
Estimated budget
1984 Hosting VPS (Iceland): €4/month : sufficient for this tutorial. Domain: ~€10/year. Annual total: ~€60 for complete digital sovereignty.
💰 Your sovereignty budget — pick a provider
Domain ~€10/year included in the total. Comparison: commercial VPN ~€72/year.
Chapter result
You have a clear vision of the final architecture and budget. You can start chapter 01.
📦 Sandbox Mode, test at €0 with Multipass (no VPS needed)
Not ready to pay for a VPS yet? Multipass creates a real Ubuntu 22.04 VM on your machine in 60 seconds. All tutorial commands work identically, the only difference is the "VPS IP" is local (192.168.x.x) instead of public.
# 1. Install Multipass (one-time) # macOS: brew install multipass # Linux (snap): sudo snap install multipass # Windows: download installer at multipass.run # 2. Create a local Ubuntu 22.04 VM (~60 s) multipass launch 22.04 --name vpn-sandbox --cpus 2 --memory 2G --disk 8G # 3. Get the VM's IP address (use this as your "VPS IP" throughout the tutorial) multipass info vpn-sandbox | grep IPv4 IPv4: 192.168.64.12 ← your local "VPS" # 4. Open a shell into the VM (replaces SSH in tutorial steps) multipass shell vpn-sandbox # When done, delete the VM multipass delete vpn-sandbox && multipass purge
⚠️ Limitation: the sandbox VM has no public IP, so the Tailscale client on your machine won't be able to connect from outside your LAN. This mode is ideal for understanding the commands before renting a real VPS.
Final result in 90 seconds
inter-node ping · DNS test · access revocation
Loading 3D scene…
Amber dashed lines = control plane: each device announces itself to your Headscale server (keys, mesh IPs). Cyan lines = data plane: traffic flows directly between devices, end-to-end encrypted — the VPS never sees it. The red observer only sees an unreadable encrypted stream.
🧠 Quiz — validate this chapter
What does the Multipass sandbox mode let you do?
Roughly how much does this VPN cost per year (VPS + domain)?
Avant de commencer
5 minObjectif de ce chapitre
Tu sais exactement ce que tu vas construire, combien ça coûte et à quoi ressemblera le résultat final. Zéro surprise.
Résultat final en 90 secondes
ping inter-nœuds · test DNS · révocation d'accès
Test rapide, 5 minutes, zéro coût, sans VPS
Avant de louer un serveur, vérifie que Docker est prêt sur ta machine et que l'image Headscale est accessible. Une seule commande, résultat immédiat :
# Lance cette commande sur TA machine (pas le VPS) docker run --rm headscale/headscale:latest headscale version headscale v0.23.0 ← tu dois voir une version ici # Si tu vois une version → Docker est prêt, on continue. # Sinon : # "docker: command not found" → installe Docker Desktop # "Cannot connect to the Docker daemon" → démarre Docker Desktop
Docker est prêt
L'image s'est chargée, la version s'affiche. Ton environnement local est opérationnel. Tu peux maintenant louer ton VPS et déployer pour de vrai.
📦 Mode Sandbox, tester à 0€ avec Multipass (sans VPS)
Pas encore prêt à payer un VPS ? Multipass crée une vraie VM Ubuntu 22.04 sur ta machine en 60 secondes. Toutes les commandes du tutoriel fonctionnent à l'identique, la seule différence : l'"IP du VPS" est locale (192.168.x.x) au lieu d'être publique.
# 1. Installer Multipass (une seule fois) # macOS : brew install multipass # Linux (snap) : sudo snap install multipass # Windows : télécharge l'installeur sur multipass.run # 2. Créer une VM Ubuntu 22.04 locale (~60 s) multipass launch 22.04 --name vpn-sandbox --cpus 2 --memory 2G --disk 8G # 3. Récupérer l'IP de la VM (utilise-la comme "IP du VPS" dans tout le tutoriel) multipass info vpn-sandbox | grep IPv4 IPv4: 192.168.64.12 ← ton "VPS" local # 4. Ouvrir un shell dans la VM (remplace le SSH des étapes du tutoriel) multipass shell vpn-sandbox # Quand tu as terminé, supprimer la VM multipass delete vpn-sandbox && multipass purge
⚠️ Limitation : la VM sandbox n'a pas d'IP publique, donc le client Tailscale sur ta machine ne pourra pas se connecter depuis l'extérieur de ton réseau local. Ce mode est idéal pour comprendre les commandes avant de louer un vrai VPS.
Saisis tes valeurs au fur et à mesure : toutes les commandes du tutoriel se réécrivent avec, et le bouton « Copier » copiera TA version. Stocké uniquement dans ton navigateur (localStorage), jamais envoyé nulle part.
Les valeurs personnalisées apparaissent surlignées comme ceci dans les commandes.
À la fin de ce tutoriel, tu auras un réseau privé WireGuard administré par Headscale, un logiciel open source qui tourne sur ton serveur. Tes appareils (ordinateur, téléphone, autres serveurs) communiqueront via ce réseau chiffré, sans passer par aucun service tiers.
Ce que tu vas construire
# Ton réseau privé à la fin du tutoriel Ton VPS (ex: 89.145.x.x) Ta machine locale ┌─────────────────────────┐ ┌──────────────────────┐ │ Headscale : 100.64.0.1 │◄──────│ Client : 100.64.0.2 │ │ Port 443 (HTTPS public)│ VPN │ Aucun port ouvert │ │ Port 51820 (WireGuard) │ ───► │ Connexion sortante │ └─────────────────────────┘ └──────────────────────┘ ↑ Internet visible par n'importe qui
Chargement de la scène 3D…
Pointillés ambre = plan de contrôle : chaque appareil s'annonce à ton serveur Headscale (clés, IPs maillées). Traits cyan = plan de données : le trafic circule en direct entre appareils, chiffré de bout en bout — le VPS ne le voit jamais. L'observateur rouge, lui, ne voit qu'un flux chiffré illisible.
Budget estimé
VPS 1984 Hosting (Islande) : 4€/mois : suffisant pour ce tutoriel. Domaine : ~10€/an. Total annuel : ~60€ pour une souveraineté numérique complète.
💰 Ton budget souveraineté — choisis un hébergeur
Domaine ~10 €/an inclus dans le calcul. Comparaison : VPN commercial ~72 €/an.
Résultat de ce chapitre
Tu as une vision claire de l'architecture finale et du budget. Tu peux commencer le chapitre 01.
🧠 Quiz — valide ce chapitre
Que permet le mode sandbox Multipass ?
Combien coûte environ ce VPN par an (VPS + domaine) ?
Why a sovereign VPN?
~15 minChapter objective
You understand the 3 real flaws of commercial VPNs. You know precisely what this tutorial protects you from, and what it doesn't.
« Privacy is necessary for an open society in the electronic age. Privacy is not secrecy. A private matter is something one doesn't want the whole world to know, but a secret matter is something one doesn't want anybody to know. »
— Eric Hughes, A Cypherpunk's Manifesto, 1993
Commercial VPNs make a simple promise: trust us with your traffic, we'll protect it. The problem? That promise relies entirely on their goodwill, and their legal resistance.
The 3 documented flaws
The CLOUD Act: one US court order is enough
Since 2018, US courts can compel any American tech company to provide data, even if stored on European servers. NordVPN, ExpressVPN, PIA are all incorporated in the US or in US-influenced countries.
"No-log" providers that handed over logs
IPVanish (2016) handed logs to the FBI despite its "zero-log" policy. PureVPN (2017) helped identify a suspect. These are not exceptions, they're the inevitable result of a marketing promise with no technical guarantee.
Dependency: you have zero control
A commercial VPN can shut down, be acquired, change its terms, or be forced to leave a country. In 2022, several VPNs left India overnight, their customers lost access without notice. You control nothing.
This tutorial does not make you anonymous
A sovereign VPN protects your independence and connection metadata. It does not anonymize you toward the sites you visit. For anonymity, Tor + Tails are more appropriate.
Chapter result
You know the 3 flaws of commercial VPNs and understand why self-hosting is the only real answer. You can move on to the technical chapters.
📜 The timeline of broken promises — click an event
2016 — IPVanish · "Zero logs", really?
IPVanish promises "zero logs"… then hands Homeland Security a user's complete history: real IP, precise timestamps. The case only surfaced in 2018 — the service never stopped calling itself "no-log".
2017 — PureVPN · The FBI says thanks
PureVPN helps the FBI identify a suspect using connection logs its "no-log" policy denied keeping. The marketing promise binds you to nothing — and binds them even less.
2018 — CLOUD Act · The law above the servers
The United States passes the CLOUD Act: any company under US law must hand over requested data, even when stored in Europe. A server "in Switzerland" doesn't protect you if the company is American.
2022 — India exodus · What a state demands…
New Delhi imposes log retention on all VPNs. ExpressVPN, NordVPN and Surfshark pull their servers out — proof that what a state demands from a provider, it eventually gets… or the provider leaves with your usage data.
A server YOU host has no provider to coerce. That's the whole point of this tutorial.
🧠 Quiz — validate this chapter
Why isn't a "no-log" promise enough?
The CLOUD Act lets US authorities demand your data…
Pourquoi un VPN souverain ?
~15 minObjectif de ce chapitre
Tu comprends les 3 failles réelles des VPNs commerciaux. Tu sais précisément ce contre quoi ce tutoriel te protège, et ce qu'il ne couvre pas.
« La vie privée est nécessaire pour une société ouverte à l'ère électronique. La vie privée n'est pas le secret. Une affaire privée est quelque chose qu'on ne veut pas que le monde entier sache, mais une affaire secrète est quelque chose qu'on ne veut pas que quiconque sache. »
— Eric Hughes, A Cypherpunk's Manifesto, 1993
Les VPNs commerciaux font une promesse simple : confie-nous ton trafic, on le protège. Le problème ? Cette promesse repose entièrement sur leur bonne volonté, et sur leur résistance légale.
Les 3 failles documentées
Le CLOUD Act : une ordonnance US suffit
Depuis 2018, la justice américaine peut contraindre n'importe quelle entreprise tech américaine à fournir des données, même stockées sur des serveurs en Europe. NordVPN, ExpressVPN, PIA sont toutes incorporées aux États-Unis ou dans des pays sous influence US.
Les "no-log" qui ont fourni des logs
IPVanish (2016) a remis des logs au FBI malgré sa politique affichée "zero-log". PureVPN (2017) a aidé à identifier un suspect. Ce ne sont pas des exceptions : c'est le résultat inévitable d'une promesse marketing sans garantie technique.
La dépendance : tu n'as aucun contrôle
Un VPN commercial peut fermer, être racheté, changer ses conditions ou être contraint de quitter un pays. En 2022, plusieurs VPNs ont quitté l'Inde du jour au lendemain, leurs clients ont perdu l'accès sans préavis. Tu ne contrôles rien.
Ce tutoriel ne te rend pas anonyme
Un VPN souverain protège ton indépendance et tes métadonnées de connexion. Il ne t'anonymise pas vis-à-vis des sites que tu visites. Pour l'anonymat, Tor + Tails sont plus adaptés.
Résultat de ce chapitre
Tu connais les 3 failles des VPNs commerciaux et tu comprends pourquoi l'auto-hébergement est la seule vraie réponse. Tu peux passer au chapitre technique.
📜 La frise des promesses trahies — clique sur un événement
2016 — IPVanish · « Zéro log », vraiment ?
IPVanish promet « zéro log »… puis fournit au Homeland Security l'historique complet d'un utilisateur : IP réelle, horodatages précis. L'affaire ne sera révélée qu'en 2018 — le service n'a jamais cessé de se dire « no-log ».
2017 — PureVPN · Le FBI remercie
PureVPN aide le FBI à identifier un suspect grâce à des logs de connexion que sa politique « no-log » niait conserver. La promesse marketing ne t'engage à rien — elle les engage encore moins.
2018 — CLOUD Act · La loi au-dessus des serveurs
Les États-Unis votent le CLOUD Act : toute entreprise soumise au droit américain doit livrer les données réclamées, même stockées en Europe. La localisation « en Suisse » d'un serveur ne protège pas si l'entreprise est américaine.
2022 — Exode de l'Inde · Ce qu'un État exige…
New Delhi impose la conservation des logs à tous les VPN. ExpressVPN, NordVPN et Surfshark retirent leurs serveurs du pays — preuve que ce qu'un État exige d'un prestataire, il finit par l'obtenir… ou le prestataire s'en va avec tes données d'usage.
Un serveur que TU héberges n'a aucun prestataire à contraindre. C'est tout l'objet de ce tutoriel.
🧠 Quiz — valide ce chapitre
Pourquoi une promesse « no-log » ne suffit-elle pas ?
Le CLOUD Act permet aux autorités américaines d'exiger tes données…
How WireGuard works
~20 minChapter objective
You understand the WireGuard mechanism without black magic: keys, tunnel, handshake. You can explain the difference with OpenVPN in 2 sentences.
Beginner Corner, What is WireGuard?
Imagine an underground tunnel between your home and your office. Everything passing through it is invisible from the street. WireGuard is that tunnel for the internet. The difference from old protocols: it fits in 4,000 lines of code instead of 100,000. Less code = fewer potential bugs = more secure.
Headscale: the orchestrator
WireGuard manages the tunnel encryption, but it doesn't know how to distribute keys between your devices. That's the role of a coordination server. Tailscale (commercial) offers this service, Headscale is the open source version you host yourself.
Result: the simplicity of Tailscale, the sovereignty of self-hosting.
# How a device joins the network: 1. The device generates a key pair (private + public) 2. It authenticates on Headscale with a pre-auth key 3. Headscale assigns it a private IP (e.g.: 100.64.0.2) 4. Headscale distributes the public key to other devices 5. Devices connect directly peer-to-peer # Result: each device knows the keys of the others # Exchanges are direct, Headscale does not see the traffic
① Your laptop generates its key pair locally. The private key will NEVER leave the device — that's the foundation of the whole security.
② It announces itself to YOUR Headscale server over HTTPS with the pre-auth key: it sends its public key and receives its private address 100.64.0.2.
③ Headscale acts as a directory: it distributes public keys to your devices. Each one now knows how to encrypt for the others.
④ Devices perform the WireGuard handshake directly (Curve25519) and derive ephemeral session keys — forward secrecy: a stolen key can't decrypt the past.
⑤ Tunnel active: ChaCha20-Poly1305 end-to-end encryption, device to device. Headscale doesn't see a single byte of data.
Pro Tip, The 100.64.0.0/10 range
This address range is reserved (CGNAT). It is never routed on the public internet, perfect for a private network invisible from the outside.
WireGuard cryptography (Expert mode)
WireGuard uses Curve25519 for Diffie-Hellman key exchange, ChaCha20-Poly1305 for symmetric encryption, and BLAKE2s for hashing. The handshake repeats every 3 minutes to ensure forward secrecy: even if a session key is compromised, past sessions remain protected.
Chapter result
You understand the role of WireGuard (encryption) and Headscale (key coordination). You can now move on to the practical steps.
👁 What your ISP sees — try it yourself
Type a message, then compare what a network observer (ISP, public Wi-Fi, employer) can read — without a tunnel, and with your WireGuard.
WITHOUT tunnel
WITH WireGuard
Illustrative scrambling (not real ChaCha20) — but from the ISP's side the effect is exactly this: unreadable bytes toward a single IP.
🧠 Quiz — validate this chapter
With WireGuard active, what does your ISP see?
Your WireGuard private key…
What is the 100.64.0.0/10 range used by your network?
Comment fonctionne WireGuard
~20 minObjectif de ce chapitre
Tu comprends le mécanisme WireGuard sans magie noire : clés, tunnel, handshake. Tu peux expliquer la différence avec OpenVPN en 2 phrases.
Coin du Débutant, C'est quoi WireGuard ?
Imagine un tunnel souterrain entre ta maison et ton bureau. Tout ce qui passe dedans est invisible depuis la rue. WireGuard, c'est ce tunnel pour internet. La différence avec les anciens protocoles : il tient en 4 000 lignes de code au lieu de 100 000. Moins de code = moins de bugs potentiels = plus sûr.
👁 Ce que voit ton FAI — essaie toi-même
Tape un message, puis compare ce qu'un observateur du réseau (FAI, Wi-Fi public, employeur) peut lire — sans tunnel, et avec ton WireGuard.
SANS tunnel
AVEC WireGuard
Brouillage illustratif (pas le vrai ChaCha20) — mais côté FAI, l'effet est exactement celui-là : des octets illisibles vers une seule IP.
Headscale : le chef d'orchestre
WireGuard gère le chiffrement du tunnel, mais il ne sait pas comment distribuer les clés entre tes appareils. C'est le rôle d'un serveur de coordination. Tailscale (commercial) propose ce service, Headscale en est la version open source que tu héberges toi-même.
Résultat : la simplicité de Tailscale, la souveraineté de l'auto-hébergement.
# Comment un appareil rejoint le réseau : 1. L'appareil génère une paire de clés (privée + publique) 2. Il s'authentifie sur Headscale avec une "pre-auth key" 3. Headscale lui attribue une IP privée (ex: 100.64.0.2) 4. Headscale distribue la clé publique aux autres appareils 5. Les appareils se connectent directement en pair-à-pair # Résultat : chaque appareil connaît les clés des autres # Les échanges sont directs, Headscale ne voit pas le trafic
① Ton laptop génère sa paire de clés localement. La clé privée ne quittera JAMAIS l'appareil — c'est la base de toute la sécurité.
② Il s'annonce à TON serveur Headscale en HTTPS avec la pre-auth key : il envoie sa clé publique et reçoit son adresse privée 100.64.0.2.
③ Headscale joue l'annuaire : il distribue les clés publiques à tes appareils. Chacun sait désormais comment chiffrer pour les autres.
④ Les appareils font le handshake WireGuard en direct (Curve25519) et dérivent des clés de session éphémères — forward secrecy : une clé volée ne déchiffre pas le passé.
⑤ Tunnel actif : chiffrement ChaCha20-Poly1305 de bout en bout, d'appareil à appareil. Headscale ne voit pas passer une seule donnée.
Pro Tip, L'IP 100.64.0.0/10
Cette plage d'adresses est réservée (CGNAT). Elle n'est jamais routée sur internet public, parfait pour un réseau privé invisible depuis l'extérieur.
Cryptographie WireGuard (mode Expert)
WireGuard utilise Curve25519 pour l'échange de clés Diffie-Hellman, ChaCha20-Poly1305 pour le chiffrement symétrique, et BLAKE2s pour le hachage. L'handshake se refait toutes les 3 minutes pour garantir la forward secrecy : même si une clé de session est compromise, les sessions passées restent protégées.
Résultat de ce chapitre
Tu comprends le rôle de WireGuard (chiffrement) et de Headscale (coordination des clés). Tu peux maintenant passer à la pratique.
🧠 Quiz — valide ce chapitre
Avec WireGuard actif, que voit ton fournisseur d'accès ?
Ta clé privée WireGuard…
À quoi correspond la plage 100.64.0.0/10 utilisée par ton réseau ?
Prepare and harden the VPS
~30 minChapter objective
Your server is operational and hardened: SSH on a non-standard port, key-only authentication, root disabled. Automated bots can no longer effectively scan it.
Beginner Corner, Why "harden" a server?
As soon as a server is online, bots continuously scan it trying to get in (port 22, password brute-force). "Hardening" = making this attack useless with 3 actions: change the SSH port, disable passwords, block root.
# Initial connection to your VPS (replace with your IP) ssh root@203.0.113.42 # Update the system first apt update && apt upgrade -y # Create a non-root user (replace "umbra" with your name) adduser umbra usermod -aG sudo umbra # Copy your SSH key to the new user rsync --archive --chown=umbra:umbra ~/.ssh /home/umbra
Beginner Corner, How does an SSH key work?
An SSH key is like a magnetic badge: you keep the badge (private key) on your computer, you put the reader (public key) on the server. No badge = no entry, even with the right password. Generate your pair with ssh-keygen -t ed25519 -C "umbra" on your local machine.
# Edit SSH configuration sudo nano /etc/ssh/sshd_config # Modify these 4 parameters: Port 50222 # Non-standard port (avoids 99% of bots) PermitRootLogin no # Never root directly PasswordAuthentication no # Keys only PubkeyAuthentication yes # Restart SSH, KEEP your current session open! sudo systemctl restart sshd # Test in a SECOND terminal BEFORE closing the first ssh -p 50222 umbra@203.0.113.42 # If it works → you can close the first terminal
NEVER close your session before testing
If the new SSH config has an error and you close your active session, you're permanently locked out. Open a second terminal, test the connection with the new port, then only close the first.
# Official Docker installation method curl -fsSL https://get.docker.com | sh # Add your user to the docker group (avoids sudo every time) sudo usermod -aG docker umbra newgrp docker # Verify docker --version Docker version 26.x.x ← expected result
Chapter result
Your VPS is secured, Docker is installed. No bot can brute-force your SSH connection anymore. You can deploy Headscale.
🧠 Quiz — validate this chapter
Before closing your SSH session after hardening, you must…
Why change the SSH port (e.g. 50222)?
Préparer et durcir le VPS
~30 minObjectif de ce chapitre
Ton serveur est opérationnel et durci : SSH sur port non-standard, authentification par clé uniquement, root désactivé. Les bots automatisés ne peuvent plus le scanner efficacement.
Coin du Débutant, Pourquoi "durcir" un serveur ?
Dès qu'un serveur est en ligne, des robots le scannent en permanence pour tenter d'y entrer (port 22, bruteforce de mots de passe). "Durcir" = rendre cette attaque inutile en 3 actions : changer le port SSH, désactiver les mots de passe, bloquer root.
# Connexion initiale à ton VPS (remplace par ton IP) ssh root@203.0.113.42 # Mettre à jour le système en premier apt update && apt upgrade -y # Créer un utilisateur non-root (remplace "umbra" par ton nom) adduser umbra usermod -aG sudo umbra # Copier ta clé SSH vers le nouvel utilisateur rsync --archive --chown=umbra:umbra ~/.ssh /home/umbra
Ça plante ? Solutions courantes, Connexion SSH
❌ "Connection refused" : Le VPS vient d'être créé : attends 2 min et réessaie.
❌ "Permission denied (publickey)" : Connecte-toi avec le mot de passe root de ton hébergeur, puis génère ta clé SSH : ssh-keygen -t ed25519
❌ "Host key verification failed" : Ancien enregistrement en cache : ssh-keygen -R 203.0.113.42
Coin du Débutant, Clé SSH : comment ça marche ?
Une clé SSH, c'est comme un badge magnétique : tu gardes le badge (clé privée) sur ton ordi, tu mets le lecteur (clé publique) sur le serveur. Pas de badge = pas d'entrée, même avec le bon mot de passe. Génère ta paire avec ssh-keygen -t ed25519 -C "umbra" sur ta machine locale.
# Éditer la configuration SSH sudo nano /etc/ssh/sshd_config # Modifier ces 4 paramètres : Port 50222 # Port non-standard (évite 99% des bots) PermitRootLogin no # Jamais root directement PasswordAuthentication no # Clés uniquement PubkeyAuthentication yes # Redémarrer SSH, GARDE ta session actuelle ouverte ! sudo systemctl restart sshd # Test dans un SECOND terminal AVANT de fermer le premier ssh -p 50222 umbra@203.0.113.42 # Si ça marche → tu peux fermer le premier terminal
Ça plante ? Solutions courantes, Durcissement SSH
❌ "Connection refused" sur le port 50222 : Le firewall bloque le nouveau port. Dans ta session actuelle : sudo ufw allow 50222/tcp && sudo ufw reload
❌ "Permission denied" : Vérifie les permissions : chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh
Ne ferme JAMAIS ta session avant de tester
Si la nouvelle config SSH a une erreur et que tu fermes ta session active, tu es définitivement lockout. Ouvre un deuxième terminal, teste la connexion avec le nouveau port, puis seulement ferme le premier.
# Méthode officielle Docker (script d'installation) curl -fsSL https://get.docker.com | sh # Ajouter ton utilisateur au groupe docker (évite sudo à chaque fois) sudo usermod -aG docker umbra newgrp docker # Vérification docker --version Docker version 26.x.x ← résultat attendu
Ça plante ? Solutions courantes, Installation Docker
❌ "docker: command not found" : La session ne connaît pas encore le groupe docker. Déconnecte-toi du SSH et reconnecte-toi.
❌ "Got permission denied while trying to connect" : Exécute newgrp docker dans la session actuelle.
Résultat de ce chapitre
Ton VPS est sécurisé, Docker est installé. Aucun robot ne peut plus bruteforcer ta connexion SSH. Tu peux déployer Headscale.
🧠 Quiz — valide ce chapitre
Avant de fermer ta session SSH après le durcissement, tu dois…
Pourquoi changer le port SSH (ex. 50222) ?
Deploy Headscale on the VPS
~30 minChapter objective
Headscale is online, accessible via HTTPS on your domain, with a namespace created and a pre-authentication key generated. You're ready to connect clients.
We'll create a config folder, write a minimal Docker Compose, and launch Headscale. HTTPS certificates will be managed automatically by Let's Encrypt.
# Create the file structure for Headscale mkdir -p /opt/headscale/{config,data} cd /opt/headscale
version: "3.9" services: headscale: image: headscale/headscale:latest restart: unless-stopped volumes: - ./config:/etc/headscale # YAML config - ./data:/var/lib/headscale # SQLite database ports: - "443:8080" # Public HTTPS - "51820:51820/udp" # WireGuard UDP command: headscale serve
# /opt/headscale/config/config.yaml # Replace vpn.yourdomain.io with your domain server_url: https://vpn.yourdomain.io listen_addr: 0.0.0.0:8080 ip_prefixes: - 100.64.0.0/10 database: type: sqlite sqlite: path: /var/lib/headscale/db.sqlite tls_letsencrypt_hostname: vpn.yourdomain.io tls_letsencrypt_cache_dir: /var/lib/headscale/cache
# Launch Headscale docker compose up -d # Verify the service responds curl https://vpn.yourdomain.io/health {"status":"pass"} ← expected result # Create a namespace (a "virtual network") docker exec headscale headscale namespaces create mynetwork # Generate a pre-auth key (valid 24h) docker exec headscale headscale preauthkeys create \ --namespace mynetwork --expiration 24h # Output: mkey:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Copy this key, you need it in chapter 05
📡 Test your DNS propagation — live
From your browser, we query DNS (Cloudflare DoH) to check that your domain points to your VPS. Nothing goes through Umbra Labs.
Chapter result
Headscale is running on your VPS, HTTPS is active, the namespace is created. You have your pre-auth key. Keep it, you need it in the next chapter.
🧠 Quiz — validate this chapter
Your Headscale server sees…
The pre-auth key you just created expires in…
Déployer Headscale sur le VPS
~30 minObjectif de ce chapitre
Headscale est en ligne, accessible via HTTPS sur ton domaine, avec un namespace créé et une clé de pré-authentification générée. Tu es prêt à connecter des clients.
On va créer un dossier de configuration, écrire un Docker Compose minimal, et lancer Headscale. Les certificats HTTPS seront gérés automatiquement par Let's Encrypt.
# Créer la structure de fichiers pour Headscale mkdir -p /opt/headscale/{config,data} cd /opt/headscale
version: "3.9" services: headscale: image: headscale/headscale:latest restart: unless-stopped volumes: - ./config:/etc/headscale # Config YAML - ./data:/var/lib/headscale # Base de données SQLite ports: - "443:8080" # HTTPS public - "51820:51820/udp" # WireGuard UDP command: headscale serve
# /opt/headscale/config/config.yaml # Remplace vpn.tondomaine.io par ton domaine server_url: https://vpn.tondomaine.io listen_addr: 0.0.0.0:8080 ip_prefixes: - 100.64.0.0/10 database: type: sqlite sqlite: path: /var/lib/headscale/db.sqlite tls_letsencrypt_hostname: vpn.tondomaine.io tls_letsencrypt_cache_dir: /var/lib/headscale/cache
# Lancer Headscale docker compose up -d # Vérifier que le service répond curl https://vpn.tondomaine.io/health {"status":"pass"} ← résultat attendu # Créer un namespace (un "réseau virtuel") docker exec headscale headscale namespaces create monreseau # Générer une clé de pré-authentification (valide 24h) docker exec headscale headscale preauthkeys create \ --namespace monreseau --expiration 24h # Output : mkey:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Copie cette clé, tu en as besoin au chapitre 05
📡 Teste ta propagation DNS — en direct
Depuis ton navigateur, on interroge le DNS (Cloudflare DoH) pour vérifier que ton domaine pointe bien vers ton VPS. Rien ne transite par Umbra Labs.
Ça plante ? Solutions courantes, Lancement Headscale
❌ "curl: (35) SSL connect error" : Le DNS n'est pas encore propagé. Vérifie : dig vpn.tondomaine.io doit retourner l'IP de ton VPS. Attends jusqu'à 5 min.
❌ "{"status":"fail"}" : Erreur de config. Consulte les logs : docker logs headscale --tail 50
❌ "Error: port is already in use" : Le port 443 est occupé. Identifie : ss -tlnp | grep 443
Résultat de ce chapitre
Headscale tourne sur ton VPS, HTTPS est actif, le namespace est créé. Tu as ta clé de pré-auth. Garde-la, elle sert au chapitre suivant.
🧠 Quiz — valide ce chapitre
Ton serveur Headscale voit passer…
La clé pre-auth que tu viens de créer expire dans…
Connect your local machine
~10 minChapter objective
Your local machine is in the VPN network. It has IP 100.64.0.2 and can reach the VPS (100.64.0.1) directly, without going through the open internet.
# Install Tailscale (Headscale-compatible client) curl -fsSL https://tailscale.com/install.sh | sh # Connect to Headscale server (replace the values) sudo tailscale up \ --login-server=https://vpn.yourdomain.io \ --authkey=mkey:xxxx \ --hostname=my-laptop # Expected result: Success.
Beginner Corner, Windows?
Download the Tailscale client from tailscale.com/download. When connecting, you can specify the Headscale server in the advanced settings instead of the CLI command.
Chapter result
Your local machine is in the VPN network with IP 100.64.0.2. The WireGuard tunnel is active. On to verification.
🖥 Pick your system — the instructions adapt
# Official install curl -fsSL https://tailscale.com/install.sh | sh # Connect to YOUR server sudo tailscale up \ --login-server=https://vpn.yourdomain.io \ --authkey=mkey:xxxx \ --hostname=my-laptop
Install the client from the Mac App Store (or brew install tailscale), then in Terminal:
sudo tailscale up \ --login-server=https://vpn.yourdomain.io \ --authkey=mkey:xxxx \ --hostname=my-mac
Download the installer from tailscale.com/download, then in PowerShell (administrator):
tailscale login \ --login-server=https://vpn.yourdomain.io \ --authkey=mkey:xxxx
1. Install the Tailscale app (App Store / Play Store).
2. On the login screen, open the menu (⋮ on Android, settings on iOS) → "Use custom coordination server".
3. Enter https://vpn.yourdomain.io then connect with your pre-auth key.
🧠 Quiz — validate this chapter
Why do we use the Tailscale client with a Headscale server?
The --authkey=mkey:… option is used to…
Connecter ta machine locale
~10 minObjectif de ce chapitre
Ta machine locale est dans le réseau VPN. Elle a l'IP 100.64.0.2 et peut joindre le VPS (100.64.0.1) directement, sans passer par internet ouvert.
# Installer Tailscale (client compatible Headscale) curl -fsSL https://tailscale.com/install.sh | sh # Connecter au serveur Headscale (remplace les valeurs) sudo tailscale up \ --login-server=https://vpn.tondomaine.io \ --authkey=mkey:xxxx \ --hostname=mon-laptop # Résultat attendu : Success. # Some peers are advertising routes but never sent traffic.
Ça plante ? Solutions courantes, Connexion client
❌ "Failed to connect to login server" : Headscale ne tourne plus. Sur le VPS : docker ps pour vérifier, docker compose up -d pour relancer.
❌ "invalid auth key" : La clé pré-auth a expiré (validité 24h). Génère-en une nouvelle : voir la commande preauthkeys create du chapitre 04.
Coin du Débutant, Windows ?
Télécharge le client Tailscale depuis tailscale.com/download. Lors de la connexion, tu peux spécifier le serveur Headscale dans les paramètres avancés au lieu de la commande CLI.
Résultat de ce chapitre
Ta machine locale est dans le réseau VPN avec l'IP 100.64.0.2. Le tunnel WireGuard est actif. Place aux vérifications.
🖥 Choisis ton système — les instructions s'adaptent
# Installation officielle curl -fsSL https://tailscale.com/install.sh | sh # Connexion à TON serveur sudo tailscale up \ --login-server=https://vpn.tondomaine.io \ --authkey=mkey:xxxx \ --hostname=mon-laptop
Installe le client depuis le Mac App Store (ou brew install tailscale), puis dans le Terminal :
sudo tailscale up \ --login-server=https://vpn.tondomaine.io \ --authkey=mkey:xxxx \ --hostname=mon-mac
Télécharge l'installeur sur tailscale.com/download, puis dans PowerShell (administrateur) :
tailscale login \ --login-server=https://vpn.tondomaine.io \ --authkey=mkey:xxxx
1. Installe l'app Tailscale (App Store / Play Store).
2. Sur l'écran de connexion, ouvre le menu (⋮ sur Android, réglages sur iOS) → « Use custom coordination server ».
3. Saisis https://vpn.tondomaine.io puis connecte-toi avec ta clé pre-auth.
🧠 Quiz — valide ce chapitre
Pourquoi utilise-t-on le client Tailscale avec un serveur Headscale ?
L'option --authkey=mkey:… sert à…
Verify, test, and go further
~10 minChapter objective
You've confirmed 0 DNS leaks, validated the WireGuard tunnel, and know how to add a new device or revoke access in under 30 seconds.
# On the VPS, see connected clients docker exec headscale headscale nodes list ID │ Hostname │ VPN IP │ Online 1 │ my-laptop │ 100.64.0.2 │ ✓ # From your local machine, ping the VPS via VPN ping 100.64.0.1 -c 4 64 bytes from 100.64.0.1: time=12.4 ms ← expected result # DNS leak test (critical!) curl https://dnsleaktest.com/test.json | python3 -m json.tool # The DNS server must match your hosting provider, NOT your ISP
🌍 What is my public IP? — live
Your Headscale network is a private network, not an exit proxy: your public IP does NOT change while browsing (unless you set up an exit node). This test shows the IP websites see — useful to verify an exit node or compare before/after.
Add a new device
Generate a new pre-auth key and repeat the procedure from chapter 05. Each device automatically gets a unique IP in the network.
Revoke access
# List nodes with their IDs docker exec headscale headscale nodes list # Delete node with ID 3 (example) docker exec headscale headscale nodes delete --identifier 3 # The device loses access immediately
Congratulations, You have an operational sovereign VPN
Your communications go through a server that only you control, in the jurisdiction of your choice, with no third party holding your keys or metadata.
🩺 Something broken? Guided diagnosis
Pick your symptom:
Likely cause: you're using the old port 22, or the firewall blocks the new one.
ssh -p 50222 umbra@203.0.113.42 sudo ufw allow 50222/tcp && sudo ufw reload
Use your provider's rescue console (KVM/VNC): check /etc/ssh/sshd_config, then systemctl restart sshd. This is exactly the lockout scenario — the rescue console is your service entrance.
First question: is DNS propagated? dig must return your VPS IP.
dig vpn.yourdomain.io +short # expected: 203.0.113.42
Fix the A record at your registrar (domain → VPS IP), wait for propagation (5 min to a few hours), then re-run the DNS test from chapter 04.
Check the Headscale logs and make sure port 443 isn't taken by another service.
docker logs headscale --tail 50 ss -tlnp | grep 443
Pre-auth keys expire after 24h. Generate a new one and reconnect.
docker exec headscale headscale preauthkeys create \
--namespace mynetwork --expiration 24h
Check both sides, then the UDP firewall.
tailscale status # on your machine docker exec headscale headscale nodes list # on the VPS sudo ufw allow 51820/udp # if a firewall is active
✓ Perfect. Head back to the final checklist to validate the rest of your setup.
🧠 Quiz — validate this chapter
One of your devices gets stolen. What do you do?
The DNS leak test checks…
Vérifier, tester et aller plus loin
~10 minObjectif de ce chapitre
Tu as confirmé 0 fuite DNS, validé le tunnel WireGuard, et tu sais ajouter un nouvel appareil ou révoquer un accès en moins de 30 secondes.
# Sur le VPS, voir les clients connectés docker exec headscale headscale nodes list ID │ Hostname │ IP VPN │ Online 1 │ mon-laptop │ 100.64.0.2 │ ✓ # Depuis ta machine locale, ping le VPS via VPN ping 100.64.0.1 -c 4 64 bytes from 100.64.0.1: time=12.4 ms ← résultat attendu # Test de fuite DNS (critique !) curl https://dnsleaktest.com/test.json | python3 -m json.tool # Le serveur DNS doit correspondre à ton hébergeur, PAS à ta box FAI
🌍 Quelle est mon IP publique ? — en direct
Ton réseau Headscale est un réseau privé, pas un proxy de sortie : ton IP publique ne change PAS en naviguant (sauf si tu configures un exit node). Ce test t'affiche l'IP que les sites voient — utile pour vérifier un exit node ou comparer avant/après.
Ajouter un nouvel appareil
Génère une nouvelle clé pré-auth et répète la procédure du chapitre 05. Chaque appareil obtient automatiquement une IP unique dans le réseau.
Révoquer un accès
# Lister les nœuds avec leurs IDs docker exec headscale headscale nodes list # Supprimer le nœud avec l'ID 3 (exemple) docker exec headscale headscale nodes delete --identifier 3 # L'appareil perd l'accès immédiatement
Bravo, Tu as un VPN souverain opérationnel
Tes communications passent par un serveur que toi seul contrôles, dans la juridiction de ton choix, sans aucun tiers qui détient tes clés ou tes métadonnées.
🩺 Ça ne marche pas ? Diagnostic guidé
Choisis ton symptôme :
Cause probable : tu utilises l'ancien port 22, ou le firewall bloque le nouveau.
ssh -p 50222 umbra@203.0.113.42 sudo ufw allow 50222/tcp && sudo ufw reload
Passe par la console de secours (KVM/VNC) de ton hébergeur : vérifie /etc/ssh/sshd_config, puis systemctl restart sshd. C'est exactement le scénario du lockout — la console de secours est ta porte de service.
Première question : le DNS est-il propagé ? dig doit retourner l'IP de ton VPS.
dig vpn.tondomaine.io +short # attendu : 203.0.113.42
Corrige l'enregistrement A chez ton registrar (domaine → IP du VPS), attends la propagation (5 min à quelques heures), puis relance le test DNS du chapitre 04.
Regarde les logs Headscale et vérifie que le port 443 n'est pas occupé par un autre service.
docker logs headscale --tail 50 ss -tlnp | grep 443
Les clés pre-auth expirent après 24 h. Régénère-en une et relance la connexion.
docker exec headscale headscale preauthkeys create \
--namespace monreseau --expiration 24h
Vérifie l'état des deux côtés, puis le firewall UDP.
tailscale status # sur ta machine docker exec headscale headscale nodes list # sur le VPS sudo ufw allow 51820/udp # si firewall actif
✓ Parfait. Retourne à la checklist finale pour valider le reste de ton installation.
🧠 Quiz — valide ce chapitre
Un de tes appareils est volé. Tu fais quoi ?
Le test DNS leak vérifie…
Checklist
Coche chaque point, sauvegardé dans ton navigateur et dans l'URL. Check each item, saved in your browser and in the URL.
GlossaireGlossary
Questions fréquentesFrequently asked questions
Prochaine étapeNext step
Déployer l'infrastructure OS-NEXUS complète Deploy the complete OS-NEXUS infrastructure
Maintenant que tu as un VPN souverain, déploie l'infrastructure multi-agents : n8n, Redis, Ollama, gVisor et 8 agents IA opérationnels. Now that you have a sovereign VPN, deploy the multi-agent infrastructure: n8n, Redis, Ollama, gVisor and 8 operational AI agents.
Tutoriel suivant →Next tutorial →Tu as aimé ce tutoriel ? Enjoyed this tutorial?
Reçois les prochains directement dans ta boîte, LLMs locaux, VPN souverain, IA sans nuage. Get the next ones in your inbox, local LLMs, sovereign VPN, cloudless AI.
Zéro spam. Désabonnement en 1 clic. Zero spam. Unsubscribe in 1 click.