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

Prêt à vous lancer ?

Choisissez vos applications et récupérez une installation complète.

Créer mon serveur