Tu en as marre de payer 12,99 €/mois à NordVPN après l'année de promo. Tu veux un tunnel chiffré qui ne soit partagé avec personne, hébergé sur une juridiction GDPR, et dont tu maîtrises la configuration ligne par ligne. Bonne nouvelle : ça se monte en 20 minutes sur un VPS Contabo à 5,50 €/mois (juin 2026), et ce guide te donne toutes les commandes. Pas de marketing, pas d'abstraction - juste le script de qualité production.
Comment auto-héberger un VPN WireGuard sur un VPS ?
L'auto-hébergement d'un VPN WireGuard prend environ 20 minutes : commander un Contabo Cloud VPS 10 (5,50 €/mois, Ubuntu 24.04), lancer apt install wireguard, générer les clés serveur, écrire un wg0.conf de 10 lignes avec subnet 10.66.66.0/24 sur le port 51820, activer le forwarding IP, et ajouter le NAT via iptables. Coût : environ 66 €/an contre ~540 € pour NordVPN sur 5 ans.
Pourquoi self-host plutôt qu'un service commercial
Un service VPN commercial te vend une promesse : pas de logs, IP partagée avec des milliers d'utilisateurs, juridiction "no-logs friendly" (Panama, BVI, Suisse). Sur le papier c'est solide. Dans la pratique :
- IP partagée = empreinte commune. Quand 4 000 utilisateurs NordVPN sortent par la même IP, tu hérites de leurs blacklists. Stripe te demandera un 3DS additionnel. Cloudflare te collera des challenges sans fin. Tu héberges ton propre VPN = ta propre IP propre.
- No-logs invérifiable en continu. Un audit PwC valide une politique sur un instant T. Entre deux audits, des assignations judiciaires (subpoenas américaines, ordonnances européennes) peuvent forcer un logging temporaire. Sur ton VPS, c'est toi qui décides. Tu purges quand tu veux.
- Prix qui doublent au renouvellement. NordVPN 2 ans : 71,76 €. Renouvellement annuel : 156 €/an. Sur 5 ans : ~600 €. Un Contabo Cloud VPS 10 sur 5 ans : ~330 €. Et tu peux héberger d'autres services dessus.
L'inconvénient est honnête : tu ne débloques pas Netflix US avec un VPS dédié (Netflix bannit les ASN datacenter). Pour le streaming, on documente une solution hybride dans le guide DPI bypass.
Choisir le bon VPS Contabo
Contabo a trois gammes pertinentes pour un VPN perso (prix juin 2026, engagement 12 mois, HT) :
| Offre | Prix / mois | vCPU | RAM | Stockage | Idéal pour |
|---|---|---|---|---|---|
| Cloud VPS 10 | 5,50 € | 4 | 8 Go | 75 Go NVMe | VPN solo 1-3 devices |
| Cloud VPS 20 | 7,50 € | 6 | 12 Go | 100 Go NVMe | VPN famille 5-10 devices |
| Cloud VPS 30 | 14 € | 8 | 24 Go | 200 Go NVMe | Multi-tunnel + autres services |
Notre choix par défaut : Cloud VPS 10 à 5,50 €/mois. Pour 90 % des usages individuels, c'est largement suffisant. Le lien à 200 Mbps+ est amplement suffisant pour un tunnel perso (lance iperf3 toi-même pour les chiffres exacts sur ta connexion).
Datacenter recommandé : Nuremberg (DE) pour des latences <30 ms depuis la France métropolitaine. Si tu es au Canada / US, prends le datacenter US Central (St. Louis).
Setup pas-à-pas
Étape 1 - Provisionner le VPS
Sur contabo.com, choisis Cloud VPS 10, Ubuntu 24.04 LTS, root password (on créera un user normal après), datacenter Nuremberg. Paiement carte ou PayPal. Activation : email reçu sous ~5 minutes avec l'IP publique et le mot de passe root.
Étape 2 - Durcir le serveur
Première connexion SSH :
ssh root@TON_IP_PUBLIQUE
# Le mot de passe est dans l'email Contabo
Crée un utilisateur non-root, ajoute ta clé SSH, désactive le login root :
adduser ericg
usermod -aG sudo ericg
mkdir -p /home/ericg/.ssh
# Colle ta clé publique (~/.ssh/id_ed25519.pub local)
nano /home/ericg/.ssh/authorized_keys
chmod 700 /home/ericg/.ssh
chmod 600 /home/ericg/.ssh/authorized_keys
chown -R ericg:ericg /home/ericg/.ssh
# Désactiver login root + password
sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh
Quitte le shell root, reconnecte-toi via ssh ericg@TON_IP. Si ça marche, on continue.
Installe firewall et fail2ban :
sudo apt update && sudo apt upgrade -y
sudo apt install -y ufw fail2ban
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 51820/udp
sudo ufw --force enable
sudo systemctl enable --now fail2ban
Étape 3 - Installer et configurer WireGuard
sudo apt install -y wireguard qrencode
# Génération clés serveur
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key
SERVER_PRIV=$(sudo cat server_private.key)
Identifie ton interface publique (souvent ens3 ou eth0) :
ip route | grep default
# default via X.X.X.X dev ens3 ...
Crée /etc/wireguard/wg0.conf :
sudo nano /etc/wireguard/wg0.conf
Contenu (remplace ens3 par ton interface si différente) :
[Interface]
PrivateKey = COLLE_SERVER_PRIV_ICI
Address = 10.66.66.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
Active le forwarding IP :
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Démarre WireGuard :
sudo systemctl enable --now wg-quick@wg0
sudo wg show
# Tu dois voir "interface: wg0" et "listening port: 51820"
Étape 4 - Générer un client
Pour chaque appareil :
cd /etc/wireguard
sudo wg genkey | sudo tee macbook_private.key | sudo wg pubkey | sudo tee macbook_public.key
CLIENT_PRIV=$(sudo cat macbook_private.key)
CLIENT_PUB=$(sudo cat macbook_public.key)
SERVER_PUB=$(sudo cat server_public.key)
Crée /tmp/macbook.conf (sur le serveur, pour générer le QR - puis tu le supprimes) :
[Interface]
PrivateKey = COLLE_CLIENT_PRIV
Address = 10.66.66.2/24
DNS = 1.1.1.1, 9.9.9.9
[Peer]
PublicKey = COLLE_SERVER_PUB
Endpoint = TON_IP_PUBLIQUE:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Ajoute ce peer au serveur :
sudo wg set wg0 peer COLLE_CLIENT_PUB allowed-ips 10.66.66.2/32
# Et persister :
sudo nano /etc/wireguard/wg0.conf
# Ajouter en bas :
# [Peer]
# PublicKey = COLLE_CLIENT_PUB
# AllowedIPs = 10.66.66.2/32
Pour iOS/Android : génère le QR-code
qrencode -t ansiutf8 < /tmp/macbook.conf
Scanne avec l'app WireGuard officielle. Active. Le tour est joué.
Étape 5 - Vérifier qu'il n'y a pas de fuite
Sur ton client connecté au tunnel :
- Va sur ipleak.net - l'IP doit être celle du VPS Contabo, pas la tienne.
- Va sur browserleaks.com/webrtc - pas d'IP locale exposée.
- Va sur dnsleaktest.com - DNS résolu via 1.1.1.1 (Cloudflare).
Si une fuite WebRTC apparaît : configure le kill switch dans WireGuard mobile (toggle "On-Demand"), ou bloque WebRTC dans Firefox (about:config → media.peerconnection.enabled → false).
Sécurisation supplémentaire
Quelques hardenings recommandés en production :
- Audit Lynis :
sudo apt install lynis && sudo lynis audit system. Score cible : 80+/100. - SSH sur port custom : modifier
/etc/ssh/sshd_configport 2222, mettre à jour UFW. - Désactiver IPv6 si non utilisé :
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1(à persister dans sysctl.conf). - Logs minimum : par défaut, journald conserve 4 semaines. Réduire à 7 jours via
/etc/systemd/journald.confsi modèle de menace strict. - Backups Contabo : activer les snapshots automatiques dans le panel Contabo (1 €/mois, pas pour les logs mais pour restaurer rapidement après une boulette).
Setup automatisé via un playbook Ansible
Si tu prévois de provisionner plus d'un VPS - ou simplement de pouvoir reconstruire ton tunnel en 3 minutes après un incident - automatiser via Ansible évite de retaper les commandes ci-dessus. Voici le playbook qu'on utilise en prod. Idempotent (tu peux le rejouer sans casser), testé sur Ubuntu 24.04 LTS Contabo Nuremberg en mai 2026.
Prérequis local
# Sur ton laptop
pip install --user ansible
mkdir -p ~/vpn-ansible && cd ~/vpn-ansible
Crée inventory.yml (remplace l'IP par celle reçue dans l'email Contabo) :
all:
hosts:
vpn1:
ansible_host: TON_IP_PUBLIQUE
ansible_user: root
ansible_python_interpreter: /usr/bin/python3
Le playbook playbook.yml
---
- name: Bootstrap VPNSmith WireGuard on Contabo
hosts: vpn1
become: yes
vars:
admin_user: ericg
admin_ssh_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
wg_subnet: "10.66.66.0/24"
wg_port: 51820
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Upgrade all packages
apt:
upgrade: dist
autoremove: yes
- name: Install hardening + WireGuard packages
apt:
name:
- ufw
- fail2ban
- wireguard
- qrencode
- unattended-upgrades
state: present
- name: Create admin user
user:
name: "{{ admin_user }}"
groups: sudo
shell: /bin/bash
password: "!"
- name: Authorize admin SSH key
authorized_key:
user: "{{ admin_user }}"
key: "{{ admin_ssh_key }}"
state: present
- name: Disable SSH root login + passwords
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regex }}"
line: "{{ item.line }}"
loop:
- { regex: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regex: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
notify: restart ssh
- name: Configure UFW default policies
ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
loop:
- { direction: incoming, policy: deny }
- { direction: outgoing, policy: allow }
- name: Allow SSH + WireGuard through UFW
ufw:
rule: allow
port: "{{ item.port }}"
proto: "{{ item.proto }}"
loop:
- { port: 22, proto: tcp }
- { port: "{{ wg_port }}", proto: udp }
- name: Enable UFW
ufw:
state: enabled
policy: deny
- name: Enable IP forwarding
sysctl:
name: net.ipv4.ip_forward
value: "1"
state: present
reload: yes
- name: Detect public interface
shell: ip -o -4 route show to default | awk '{print $5}'
register: pub_iface
changed_when: false
- name: Generate server WireGuard keys
shell: |
umask 077
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
args:
creates: /etc/wireguard/server_private.key
- name: Read server keys
slurp:
src: "/etc/wireguard/{{ item }}"
register: wg_keys
loop:
- server_private.key
- server_public.key
- name: Render wg0.conf
copy:
dest: /etc/wireguard/wg0.conf
mode: '0600'
content: |
[Interface]
PrivateKey = {{ wg_keys.results[0].content | b64decode | trim }}
Address = 10.66.66.1/24
ListenPort = {{ wg_port }}
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE
- name: Enable + start wg-quick@wg0
systemd:
name: wg-quick@wg0
enabled: yes
state: started
- name: Enable + start fail2ban
systemd:
name: fail2ban
enabled: yes
state: started
handlers:
- name: restart ssh
systemd:
name: ssh
state: restarted
Exécution
ansible-playbook -i inventory.yml playbook.yml
Compter ~3 minutes la première fois (essentiellement l'upgrade apt). Le tunnel est up. Ton utilisateur ericg peut SSH avec sa clé Ed25519. Tu peux rejouer le playbook autant de fois que tu veux, il ne réécrira pas les clés WireGuard (idempotence garantie par le creates:).
Pour ajouter un client (à ajouter dans une seconde phase du playbook, on la documente dans le guide WireGuard config templates) : tu génères les clés client, tu rends le client.conf en Jinja2, tu pushes la conf via QR encode.
Petit conseil pratique : versionne le playbook dans un repo Git privé (jamais public - les clés Ansible Vault ne sont pas un secret face à GitHub public si la passphrase fuite). On utilise un repo Gitea auto-hébergé sur le même VPS pour la circularité parfaite.
Monitoring uptime gratuit avec UptimeRobot
Si tu veux savoir quand ton tunnel tombe sans rafraîchir manuellement, UptimeRobot couvre 95 % du besoin gratuitement. Plan free : 50 monitors, check toutes les 5 minutes, alertes email + Telegram + Discord webhook.
On surveille 3 endpoints distincts pour distinguer la nature de la panne :
Monitor 1 - Santé serveur (ping HTTPS de l'IP)
UptimeRobot type "HTTP(s)", URL https://TON_IP_PUBLIQUE/healthz. Pour répondre à ce check, installe un caddy léger sur le port 443 :
sudo apt install -y caddy
sudo tee /etc/caddy/Caddyfile > /dev/null <<EOF
:443 {
respond /healthz "OK" 200
tls internal
}
EOF
sudo systemctl restart caddy
sudo ufw allow 443/tcp
Si ce monitor passe à DOWN → le VPS lui-même est inaccessible (réseau Contabo en rade, ou ton VPS a planté).
Monitor 2 - Santé tunnel (depuis Cloudflare Workers)
Crée un Cloudflare Worker gratuit (free tier 100 000 req/jour) qui fait un fetch vers https://ifconfig.me à travers un user-agent custom. Pour que ce check ait du sens il faut que le Worker passe par le tunnel WireGuard, ce qui n'est pas possible directement avec Workers - on contourne avec un monitor "Keyword" UptimeRobot qui interroge un endpoint hébergé chez toi et vérifie que la réponse contient l'IP du VPS Contabo (pas une IP résidentielle).
URL surveillée : https://TON_IP_PUBLIQUE/whoami (caddy redirige vers ifconfig.me).
Keyword : l'IP IPv4 de ton VPS.
Si le tunnel routait mal (DNS hijack, NAT cassé), l'IP retournée serait différente et le monitor passerait alert.
Monitor 3 - Santé DNS via 1.1.1.1
URL : https://1.1.1.1/cdn-cgi/trace, keyword "warp=off". Ce check vérifie que tu peux résoudre Cloudflare depuis le VPS - c'est-à-dire que la route sortante du VPS n'est pas cassée.
Configuration des alertes
Sur UptimeRobot, configure :
- Email primary : tu reçois sous 30 sec après détection
- Telegram bot (gratuit) : alerte push sur ton phone même hors mail
- Threshold : "alert after 2 failed checks" pour éviter les faux positifs réseau
En pratique, ce setup t'alerte surtout sur des événements réels - une maintenance Contabo planifiée, ou un crash de service (par exemple Caddy qui échoue sur un renouvellement de certificat). Avec le seuil « 2 checks échoués », les faux positifs réseau restent rares.
Coût total : 0 €. UptimeRobot free + Cloudflare Workers free + Caddy gratuit.
Hardening SSH avec fail2ban et key-only auth
Le bootstrap initial désactive le password SSH, mais en production il faut aller plus loin. Voici le hardening à appliquer sur tout VPS Contabo, motivé par le scan SSH automatisé permanent que subit tout hôte exposé sur internet (les bots scannent en continu les plages d'IP des hébergeurs, Contabo incluse).
Étape 1 - Port SSH custom
Changer le port SSH n'est pas de la "vraie" sécurité (security through obscurity) mais ça réduit les logs de 95 %. Les bots scannent prioritairement le port 22.
sudo sed -i 's/^#Port 22/Port 2289/' /etc/ssh/sshd_config
sudo ufw delete allow 22/tcp
sudo ufw allow 2289/tcp
sudo systemctl restart ssh
# Vérifie depuis un autre terminal AVANT de fermer le premier :
# ssh -p 2289 ericg@TON_IP
⚠ Garde ton ancien terminal ouvert tant que tu n'as pas vérifié la connexion sur le nouveau port. Sinon tu te lockes out.
Étape 2 - fail2ban jail SSH custom
Par défaut fail2ban surveille le port 22. À adapter :
sudo tee /etc/fail2ban/jail.d/sshd-custom.local > /dev/null <<EOF
[sshd]
enabled = true
port = 2289
maxretry = 3
findtime = 600
bantime = 86400
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Politique : 3 échecs en 10 minutes → ban 24h. Plus stricte que le default (5 échecs / 1h ban) parce qu'on n'autorise pas les passwords de toute façon - un échec d'auth c'est un bot.
Étape 3 - Audit du quota fail2ban
Le jail SSH typique bannit 30-80 IP/jour sur Contabo Nuremberg. Pour vérifier ce qui se passe :
sudo fail2ban-client status sshd
# Currently banned IPs: 47
# Banned IP list: 185.x.x.x 91.x.x.x ...
sudo zcat /var/log/fail2ban.log* | grep "Ban " | wc -l
# Total des ban depuis le début
Si tu voies >200 ban/jour, tu peux durcir bantime = 604800 (1 semaine) pour limiter la charge IO sur le serveur.
Étape 4 - Clés SSH Ed25519 + passphrase
Si tu n'as pas généré ta clé Ed25519 sur le laptop, c'est le moment :
# Sur ton laptop
ssh-keygen -t ed25519 -C "ericg@laptop-2026" -f ~/.ssh/id_ed25519_vpn
# Choisis une passphrase forte (saisie 1 fois/jour via ssh-agent)
ssh-add -t 10800 ~/.ssh/id_ed25519_vpn # désactive après 3h
Ed25519 > RSA 4096 : signatures plus rapides, clés plus courtes, état de l'art en 2026. Tous les VPS Contabo Ubuntu 24.04 supportent Ed25519 nativement.
Étape 5 - Désactiver les ChallengeResponseAuthentication
Vérifie que ces lignes sont bien dans /etc/ssh/sshd_config :
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
AuthenticationMethods publickey
Avec AuthenticationMethods publickey, même si une CVE 0-day permet à un attaquant de bypasser PAM, il faudra toujours la clé. Belt and suspenders.
Après ces 5 étapes, l'essentiel des tentatives SSH automatisées est bloqué au pare-feu et le reste ne peut jamais s'authentifier (login par clé uniquement). Aucune ne réussit. Tu peux dormir tranquille.
Coût mensuel : Contabo Cloud VPS 10 vs NordVPN annuel
Le calcul honnête sur 5 ans (Contabo 5,50 €/mois, juin 2026) :
| Solution | An 1 | An 2 | An 3 | An 4 | An 5 | Total |
|---|---|---|---|---|---|---|
| NordVPN 2 ans + renouvellements | 71,76 € | 0 € | 156 € | 156 € | 156 € | 539,76 € |
| Contabo Cloud VPS 10 (5,50 €/mois) | 66 € | 66 € | 66 € | 66 € | 66 € | 330 € |
Économie : ~210 € sur 5 ans, soit 39 %. Et tu héberges en bonus ton Bitwarden, ton Nextcloud, ton Umami, ce que tu veux.
Limitations honnêtes du self-host
Pour être complet :
- Streaming Netflix US, BBC iPlayer, etc. : ne marche quasiment jamais. Netflix détecte les ASN datacenter (Contabo ASN 51167) et te sert le catalogue local. Pour le streaming, garde un NordVPN 1 an en complément.
- Bypass DPI Iran/Chine : WireGuard sur port 51820/udp en clair est détecté par DPI sophistiqué. Pour ces cas, ajoute V2Ray ou Cloak en obfuscation (cf. le guide dédié).
- Pas de chat support : Contabo répond par email sous 24-48h. Si tu veux du chat live, regarde Hetzner Cloud (~2× le prix, support FR/DE/EN par chat).
- Tu es admin : si le VPS plante, tu débogges. C'est l'inverse d'un service managé.
Pour aller plus loin
- Contabo vs Hetzner vs OVH : VPS Europe pour VPN self-host 2026
- WireGuard vs OpenVPN sur VPS : benchmarks réels 2026
- Routing VPN custom sur Contabo : bypass DPI Iran/Chine 2026
- VPN site à site WireGuard : relier deux réseaux entiers 2026
- Générateur de config WireGuard - générez serveur + clients prêts à coller en 30 secondes
- Calculateur de coût VPN auto-hébergé - comparez Contabo vs NordVPN sur 1, 2 et 5 ans
- Comparateur VPS interactif - filtrez Contabo/Hetzner/OVH par latence, RAM et prix 24 mois
- Sources officielles : WireGuard whitepaper, Contabo docs VPS, Ubuntu 24.04 hardening guide
Article publié le 2026-06-02, dernière mise à jour 2026-06-03 (ajout : playbook Ansible idempotent, monitoring UptimeRobot gratuit en 3 endpoints, hardening SSH fail2ban + Ed25519). Dernière vérification du script bootstrap sur Ubuntu 24.04 LTS le 2026-06-03. Si la procédure casse chez toi, ouvre une issue sur notre GitHub ou écris à contact@vpnsmith.com.
★ Datacenter Nuremberg GDPR · ✓ IPv4 dédiée incluse · 200+ Mbps garantis
Héberge ton VPN sur ton propre VPS → ContaboAccès root complet · IPv4 publique · choisis ta région→

