Les bases
Sécuriser son VPS en 10 étapes (Ubuntu / Debian)
Mis à jour le 3 octobre 2026 · 12 min de lecture
Un VPS fraîchement installé est scanné par des robots dans les minutes qui suivent sa mise en ligne. Ce guide reprend, dans l’ordre, les étapes que j’applique sur mes propres serveurs, y compris les pièges qui m’ont fait perdre du temps.
Les commandes sont pour Ubuntu 24.04 / 26.04 et Debian 12 / 13.
1. Mettre le système à jour
Première chose à faire, avant tout le reste :
sudo apt update && sudo apt full-upgrade -y
Vérifiez aussi que votre version est encore maintenue. Une version d’Ubuntu non-LTS (25.04, 25.10…) n’est suivie que 9 mois : passé ce délai, plus aucun correctif de sécurité. Sur un serveur, prenez toujours une version LTS (24.04, 26.04), maintenue 5 ans.
grep PRETTY /etc/os-release
2. Se connecter par clé SSH
Sur votre ordinateur (pas sur le serveur), créez une clé si vous n’en avez pas :
ssh-keygen -t ed25519
Puis envoyez-la sur le serveur :
ssh-copy-id utilisateur@IP_DU_SERVEUR
Sous Windows, ssh-copy-id n’existe pas : copiez le contenu de C:\Users\VOUS\.ssh\id_ed25519.pub à la fin du
fichier ~/.ssh/authorized_keys sur le serveur.
Testez la connexion par clé dans un nouveau terminal avant de passer à l’étape suivante.
3. Interdire les mots de passe en SSH
Créez un fichier de configuration dédié :
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
Le piège : le nom du fichier compte. Beaucoup d’hébergeurs (OVH, Scaleway…) installent un fichier
50-cloud-init.conf qui contient PasswordAuthentication yes. SSH garde la première valeur lue et lit les
fichiers par ordre alphabétique : un fichier nommé 99-hardening.conf serait donc ignoré. Le préfixe 00- garantit
qu’il passe en premier.
Vérifiez la syntaxe, rechargez, puis contrôlez la configuration réellement appliquée :
sudo sshd -t && sudo systemctl reload ssh
sudo sshd -T | grep -E "passwordauthentication|permitrootlogin"
Les deux lignes doivent afficher no. Depuis votre PC, une tentative par mot de passe doit être refusée :
ssh -o PubkeyAuthentication=no utilisateur@IP_DU_SERVEUR
# → Permission denied (publickey)
4. Activer le pare-feu
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
N’autorisez que ce qui doit être joignable depuis Internet. Les interfaces d’administration (tableaux de bord, bases de données…) ne doivent jamais être ouvertes publiquement.
5. Attention : Docker contourne UFW
C’est le piège le plus dangereux. Docker ajoute ses propres règles iptables, avant celles d’UFW. Un conteneur
lancé avec :
ports:
- "9100:9100"
est accessible depuis tout Internet, même si UFW bloque le port 9100. Vérifiez depuis l’extérieur, pas
seulement avec ufw status.
La solution : publier les ports uniquement en local, puis passer par un reverse proxy.
ports:
- "127.0.0.1:9100:9100"
Le générateur docker-compose applique cette règle automatiquement.
6. Mises à jour de sécurité automatiques
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Les correctifs de sécurité s’installent alors chaque jour, sans intervention. Pour les mises à jour du noyau, un
redémarrage reste nécessaire : le fichier /var/run/reboot-required existe quand c’est le cas.
7. Bloquer les attaques avec CrowdSec
CrowdSec analyse les journaux (SSH, Nginx, Traefik…) et bloque les adresses IP qui scannent ou attaquent votre serveur. Il partage aussi une liste communautaire d’IP malveillantes : vous êtes protégé contre des attaquants repérés ailleurs, avant même qu’ils vous ciblent.
C’est une alternative moderne à Fail2ban. Si votre SSH n’accepte que les clés (étape 3), le brute-force SSH est déjà inoffensif : CrowdSec est surtout utile devant vos sites web.
8. Ne pas faire tourner les conteneurs en root
Par défaut, un processus dans un conteneur tourne en root. En cas de faille dans l’application, l’attaquant
démarre avec les pleins pouvoirs. Quand l’image le permet, ajoutez dans le docker-compose.yml :
user: "1000:1000"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
Encore mieux : un utilisateur système dédié par application, propriétaire de ses seules données
(chmod 700). Une application compromise ne peut alors pas lire les données des autres. Tout le détail, conteneur
par conteneur : sécuriser ses conteneurs Docker.
9. Protéger le socket Docker
Monter /var/run/docker.sock dans un conteneur (Traefik, Portainer, Watchtower…) lui donne un accès root complet
au serveur. Si ce conteneur est compromis, tout le serveur l’est.
Placez un socket-proxy entre les deux : il ne laisse passer que les appels en lecture dont le service a besoin.
socket-proxy:
image: tecnativa/docker-socket-proxy:latest
environment:
CONTAINERS: 1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Le service se connecte alors à tcp://socket-proxy:2375 au lieu du socket.
10. Sauvegarder… ailleurs
Une sauvegarde stockée sur le même serveur disparaît avec lui. La règle 3-2-1 :
- 3 copies de vos données ;
- sur 2 supports différents ;
- dont 1 hors du serveur (autre hébergeur, NAS à la maison…).
Des outils comme restic ou Borg chiffrent et dédupliquent les sauvegardes. Et surtout : testez une restauration de temps en temps. Une sauvegarde jamais testée n’est qu’un espoir.
Récapitulatif
| Étape | Commande clé | Protège contre |
|---|---|---|
| Mises à jour | apt full-upgrade |
failles connues |
| Clés SSH | ssh-copy-id |
vol de mot de passe |
| SSH sans mot de passe | 00-hardening.conf |
brute-force |
| Pare-feu | ufw enable |
services exposés par erreur |
| Docker et UFW | 127.0.0.1:port |
ports ouverts malgré UFW |
| Mises à jour auto | unattended-upgrades |
oubli |
| CrowdSec | cscli decisions list |
scans et attaques web |
| Conteneurs non-root | user: |
propagation d’une faille |
| Socket-proxy | CONTAINERS: 1 |
prise de contrôle via Docker |
| Sauvegardes externes | restic, Borg | perte totale |