Sécuriser un VPS Linux ne consiste pas à installer UFW et Fail2ban puis à considérer le travail terminé. Un serveur exposé à Internet doit être défendu en profondeur : système maintenu, accès administratifs nominatifs, authentification SSH robuste, ports strictement nécessaires, services exécutés avec le minimum de privilèges, journaux exploitables, sauvegardes restaurables et procédure de réaction en cas de compromission.
Ce guide propose un socle réaliste pour Debian et Ubuntu. Chaque changement sensible est accompagné d'un contrôle et, lorsque c'est nécessaire, d'une précaution contre le verrouillage à distance.
À la fin, vous devez pouvoir répondre précisément à ces questions :
- quelle version du système est installée et jusqu'à quand est-elle maintenue ?
- quels services écoutent sur IPv4 et IPv6 ?
- qui peut se connecter en SSH, avec quelle méthode et depuis quel réseau ?
- quelles règles de pare-feu sont réellement appliquées ?
- les correctifs de sécurité sont-ils installés et leurs échecs sont-ils signalés ?
- les journaux survivent-ils à un redémarrage et sont-ils copiés hors du VPS ?
- quelle est la dernière sauvegarde restaurée avec succès ?
- que ferez-vous si une clé, un compte ou le serveur entier est compromis ?
Méthode, périmètre et limites
Les recommandations ont été recoupées le 31 août 2026 avec les publications de l'ANSSI sur le durcissement GNU/Linux, la documentation officielle de Debian, d'Ubuntu Server, d'OpenSSH, de systemd, du noyau Linux, de Docker et de restic. Le guide ANSSI GNU/Linux fournit un cadre de durcissement ; les commandes et comportements susceptibles d'évoluer ont été vérifiés dans les documentations actuelles des projets.
Les versions, les dates de support et le comportement des outils changent. Avant d'appliquer ce socle en production, exécutez-le sur un VPS de test et vérifiez les valeurs datées de cet article sur les pages officielles liées au fil du texte.
Ce guide couvre un VPS Debian ou Ubuntu administré directement. Il ne remplace pas le durcissement propre à Nginx, Apache, PHP, Docker, une base de données ou une application, ni une architecture haute disponibilité, ni un audit réglementaire ou un test d'intrusion, ni les règles spécifiques à Kubernetes, Proxmox, un routeur, un serveur de messagerie ou un hyperviseur, ni les mesures prises par l'hébergeur sous la couche virtuelle.
La sécurité est une propriété de l'ensemble : hébergeur, réseau, système, application, identités, données, sauvegardes et exploitation.
Versions prises en compte en août 2026
Debian 13 « trixie » est la version stable actuelle. Debian indique un support complet jusqu'au 9 août 2028, puis une phase LTS jusqu'au 30 juin 2030, avec un jeu d'architectures réduit pendant cette phase. Debian 12 est désormais remplacée par Debian 13 : son support complet s'est terminé le 11 juillet 2026 et elle reste couverte par sa phase LTS jusqu'au 30 juin 2028, limitée à certaines architectures. Consultez les pages officielles Debian 13 et Debian 12.
Ubuntu 22.04, 24.04 et 26.04 sont des versions LTS encore maintenues en août 2026. Canonical publie les dates exactes dans son cycle de vie Ubuntu.
| Système | Situation au 31 août 2026 | Décision conseillée |
|---|---|---|
| Debian 13 | stable actuelle | choix Debian recommandé pour une nouvelle installation |
| Debian 12 | LTS, support plus limité selon l'architecture | planifier la migration vers Debian 13 |
| Ubuntu 26.04 LTS | LTS actuelle | choix Ubuntu recommandé après validation de la compatibilité applicative |
| Ubuntu 24.04 LTS | maintenance standard jusqu'en 2029 | excellent choix pour une pile déjà qualifiée |
| Ubuntu 22.04 LTS | maintenance standard jusqu'en 2027 | prévoir la montée de version |
| version en fin de support | plus de correctifs normaux | migrer ; le pare-feu ne compense pas un système non maintenu |
N'utilisez pas uniquement uname -r pour juger la sécurité d'un système. Debian et Ubuntu rétroportent des correctifs sans forcément adopter le numéro de version amont le plus récent. Vérifiez une CVE dans le Debian Security Tracker ou le suivi des CVE Ubuntu, avec la distribution et le paquet réellement installés.
Modèle de menace : ce que le guide cherche à réduire
Un VPS public est notamment exposé aux scans automatisés et aux tentatives d'authentification, à l'exploitation d'un service ou d'une dépendance non corrigée, au vol d'une clé SSH, d'un jeton API ou d'un secret applicatif, à une erreur de pare-feu, de droits ou de publication Docker, à l'escalade de privilèges après compromission d'une application, à l'effacement ou au chiffrement des données et des sauvegardes accessibles, à la suppression des journaux par un attaquant devenu administrateur, et à une erreur humaine pendant une mise à jour ou un changement réseau.
Ce socle ne rend pas le VPS invulnérable. Il cherche à diminuer la probabilité d'intrusion, limiter l'impact d'un premier accès, améliorer la détection et permettre une reconstruction maîtrisée.
Trois niveaux de maturité
| Niveau | Mesures minimales | Usage |
|---|---|---|
| Socle | inventaire, mises à jour, compte nominatif, clé SSH, root et mot de passe SSH désactivés, pare-feu, sauvegarde distante | tout VPS exposé |
| Production | mises à jour supervisées, AppArmor, Fail2ban selon le risque, journaux persistants et distants, alertes externes, restauration testée | site ou service de production |
| Renforcé | administration par VPN ou bastion, clé FIDO2 ou MFA, filtrage sortant étudié, auditd/AIDE, dépôt de sauvegarde append-only, configuration déclarative | données sensibles ou fortes exigences |
Toutes les mesures ne doivent pas être appliquées aveuglément. Désactiver le transfert IP, par exemple, casse un routeur, un VPN ou certains réseaux de conteneurs. Le durcissement professionnel commence par le contexte.
Avant toute modification : éviter de vous verrouiller dehors
Avant de toucher à SSH ou au pare-feu :
- vérifiez que la console de secours de l'hébergeur fonctionne ;
- conservez la session SSH actuelle ouverte ;
- ouvrez une seconde fenêtre pour tester chaque changement ;
- relevez l'adresse et le port SSH effectifs ;
- créez un snapshot de précaution si la plateforme le permet ;
- sauvegardez les fichiers modifiés ;
- ne désactivez l'ancien accès qu'après avoir validé le nouveau.
Un snapshot pris avant changement facilite un retour arrière opérationnel, mais il ne remplace pas une sauvegarde hors du VPS. Il peut être incohérent si une base écrit au même instant et il reste généralement administré depuis le même compte fournisseur.
1. Inventorier le système avant de le durcir
Commencez par une collecte en lecture seule :
cat /etc/os-release
uname -a
hostnamectl
systemd-detect-virt
ip -brief address
ip route
ip -6 route
sudo ss -lntup
sudo systemctl --type=service --state=running --no-pager
sudo systemctl list-unit-files --state=enabled --no-pager
df -hT
df -ih
findmnt
timedatectl
ss -lntup liste les sockets en écoute. Pour voir les connexions TCP établies, dont des connexions sortantes :
sudo ss -tpn state established
Créez une fiche d'exploitation avec :
| Élément | Valeur à consigner |
|---|---|
| distribution et version | résultat de /etc/os-release |
| noyau et architecture | résultat de uname -a |
| IPv4 et IPv6 publiques | adresses réellement routées |
| interface principale | nom, adresse, passerelle |
| ports attendus | par exemple 22, 80 et 443 TCP |
| services attendus | SSH, Nginx, application, agent de supervision |
| administrateurs autorisés | comptes nominatifs, clés et origine réseau |
| données critiques | fichiers, bases, secrets et configurations |
| RPO/PDMA | perte de données maximale acceptable |
| RTO/DMIA | durée d'interruption maximale acceptable |
Tout port sans propriétaire ni justification doit être étudié avant d'être fermé. Un service peut écouter uniquement sur 127.0.0.1, sur une adresse privée, sur toutes les interfaces IPv4 avec 0.0.0.0, ou sur IPv6 avec ::. Contrôlez les deux familles.
2. Utiliser des comptes nominatifs et le moindre privilège
Évitez l'administration quotidienne avec un compte partagé ou directement avec root. Créez un compte par administrateur afin que les journaux et les révocations restent attribuables.
Exemple avec adminops :
sudo adduser adminops
sudo usermod -aG sudo adminops
sudo groupadd --force ssh-admins
sudo usermod -aG ssh-admins adminops
id adminops
getent group ssh-admins
Sur Debian et Ubuntu, les membres du groupe sudo peuvent obtenir des privilèges conformément à la politique locale. Ubuntu explique l'intérêt de sudo pour la traçabilité dans sa documentation sur la gestion des utilisateurs.
Depuis le poste de l'administrateur, générez une clé moderne protégée par une phrase secrète :
ssh-keygen -t ed25519 -a 100 -C "adminops@organisation"
ssh-copy-id -i ~/.ssh/id_ed25519.pub adminops@ADRESSE_DU_VPS
Ed25519 est le choix recommandé dans la documentation OpenSSH d'Ubuntu. L'option -a augmente le nombre de tours de la fonction de dérivation qui protège la clé privée par sa phrase secrète ; elle ne modifie pas l'algorithme de la clé. Notre guide configurer une clé SSH sur un VPS Linux détaille la procédure côté Windows, macOS et Linux.
Pour un niveau renforcé, une clé FIDO2 de type ed25519-sk impose la présence d'un authentificateur matériel compatible :
ssh-keygen -t ed25519-sk -C "adminops-fido2@organisation"
Conservez une méthode de récupération distincte, protégée et testée. Une seule clé matérielle sans procédure de secours transforme sa perte en incident de disponibilité.
Testez dans une nouvelle fenêtre :
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 adminops@ADRESSE_DU_VPS
sudo -v
id
Ne poursuivez pas tant que la connexion par clé et sudo ne fonctionnent pas.
Auditer les comptes existants
getent passwd
awk -F: '($3 == 0) {print $1}' /etc/passwd
sudo lastlog
sudo passwd -S root
Il ne doit normalement exister qu'un seul UID 0. Verrouillez ou supprimez les comptes devenus inutiles après avoir vérifié leurs fichiers, tâches planifiées, processus et dépendances applicatives.
3. Durcir OpenSSH sans interrompre l'accès
Ubuntu accepte la configuration principale dans /etc/ssh/sshd_config et les fragments dans /etc/ssh/sshd_config.d/. Sa configuration inclut normalement ce répertoire en haut du fichier principal. OpenSSH retient la première valeur rencontrée pour la majorité des directives ; un fichier nommé 00-hardening.conf est donc plus prévisible qu'un fichier tardif qui pourrait passer après un fragment créé par cloud-init. Ce comportement est documenté par Ubuntu et dans le manuel sshd_config de Debian.
Vérifiez d'abord l'inclusion :
grep -nE '^[[:space:]]*Include' /etc/ssh/sshd_config
sudo sshd -T | sort
Sauvegardez la configuration :
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.before-hardening
sudo install -d -m 755 /etc/ssh/sshd_config.d
sudoedit /etc/ssh/sshd_config.d/00-hardening.conf
Ajoutez :
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey
AllowGroups ssh-admins
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
PermitTunnel no
Avant le rechargement :
sudo sshd -t
sudo sshd -T | grep -E '^(port|permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|allowgroups|maxauthtries|logingracetime|x11forwarding|permittunnel) '
Si des blocs Match existent, contrôlez aussi la configuration appliquée au compte et à l'adresse d'administration :
sudo sshd -T \
-C user=adminops,host="$(hostname -f)",addr=198.51.100.10 |
grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|allowgroups) '
L'adresse 198.51.100.10 appartient à une plage réservée aux exemples. Remplacez-la par l'adresse réelle depuis laquelle l'administrateur se connectera.
Si sshd -t ne retourne rien, la syntaxe est valide. Rechargez sans fermer la session actuelle :
sudo systemctl reload ssh
sudo systemctl status ssh --no-pager
sudo journalctl -u ssh -n 50 --no-pager
Testez immédiatement une nouvelle connexion avec la clé, puis sudo -v. Ne fermez l'ancienne session qu'après ce test.
Ce qui doit rester conditionnel
AllowTcpForwarding noetAllowAgentForwarding nosont utiles si aucun tunnel ni rebond SSH n'est nécessaire, mais ils cassent ces usages ;- restreindre SSH à une adresse IP ou à un VPN réduit fortement l'exposition, mais exige un chemin de secours ;
- changer le port 22 réduit surtout le bruit des robots ; cela ne remplace ni une clé, ni un pare-feu, ni les correctifs ;
- un MFA TOTP peut compléter la clé. La documentation Ubuntu décrit la combinaison
AuthenticationMethods publickey,keyboard-interactivedans son guide TOTP/HOTP.
4. Installer et superviser les mises à jour de sécurité
Une commande avec -y est pratique dans un laboratoire, mais un premier durcissement de production doit permettre de lire les changements proposés :
sudo apt update
apt list --upgradable
sudo apt-get -s upgrade
sudo apt upgrade
sudo apt autoremove --dry-run
Exécutez apt autoremove seulement après avoir vérifié la liste. Une mise à jour de distribution, un noyau, un pilote ou un paquet métier peut nécessiter un redémarrage et un test applicatif.
Activer les correctifs automatiques
Sur Ubuntu Server, unattended-upgrades est installé et les mises à jour de sécurité sont normalement activées par défaut. Ne le supposez pas : contrôlez-le. La documentation Ubuntu sur les mises à jour automatiques précise les fichiers, les timers, les origines autorisées et les journaux.
Sur Debian, installez et activez explicitement le mécanisme selon votre politique :
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
systemctl list-timers 'apt-daily*' --all
sudo unattended-upgrade --dry-run --debug
sudo journalctl -u apt-daily-upgrade.service -n 100 --no-pager
Contrôlez notamment :
grep -RhsE 'APT::Periodic::(Update-Package-Lists|Unattended-Upgrade)' \
/etc/apt/apt.conf.d/
sudo sed -n '/Allowed-Origins/,/};/p' \
/etc/apt/apt.conf.d/50unattended-upgrades
Une origine tierce n'est pas automatiquement couverte. Vérifiez quels dépôts fournissent les paquets :
grep -RhsE '^[[:space:]]*(deb |Types:|URIs:|Suites:|Signed-By:)' \
/etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null
apt-cache policy
Sur Debian 13, les notes de publication proposent aussi cette recherche des paquets installés qui ne proviennent pas de Debian :
apt list '?narrow(?installed, ?not(?origin(Debian)))'
Un dépôt ajouté pour un seul paquet élargit la chaîne de confiance et peut fournir des mises à jour à d'autres paquets. Utilisez les dépôts officiels ou ceux de l'éditeur, une clé dédiée via Signed-By, et supprimez les sources devenues inutiles. Évitez d'exécuter directement curl ... | sh sans télécharger, vérifier et relire le script.
Redémarrages et alertes
Sur Ubuntu, un redémarrage recommandé est généralement signalé par :
if [ -f /var/run/reboot-required ]; then
cat /var/run/reboot-required
cat /var/run/reboot-required.pkgs 2>/dev/null
fi
L'automatisation sans supervision est incomplète. Alertez au minimum sur l'échec du timer ou du service de mise à jour, l'âge de la dernière exécution réussie, un redémarrage requis depuis trop longtemps, un paquet bloqué ou une origine non couverte, et un système proche de sa fin de support.
5. Configurer le pare-feu : choisir un seul gestionnaire
Un pare-feu n'est pas un outil d'inventaire : déterminez d'abord les flux légitimes. Il complète le durcissement des services mais ne le remplace pas, comme le rappelle le manuel de sécurité Debian.
Choisissez une approche principale :
| Contexte | Choix conseillé |
|---|---|
| Ubuntu, règles simples | UFW |
| Debian, politique native et avancée | nftables |
| Docker Engine | étudier d'abord les chaînes et limites Docker |
| infrastructure avec pare-feu fournisseur | appliquer aussi le filtrage réseau, sans abandonner le pare-feu local |
UFW est l'outil de pare-feu par défaut documenté par Ubuntu. nftables est le framework par défaut et recommandé par Debian. N'empilez pas UFW, un ruleset nftables manuel et d'autres gestionnaires sans comprendre leur ordre.
Option A : UFW sur Ubuntu ou pour un besoin simple
Relevez le port SSH effectif :
sudo sshd -T | awk '$1 == "port" {print $2; exit}'
L'exemple suivant suppose SSH sur 22, ainsi qu'un serveur web. Adaptez les ports avant l'activation :
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH administration'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw show added
sudo ufw enable
sudo ufw status verbose
sudo ufw status numbered
Conservez la session ouverte et testez une nouvelle connexion SSH.
Si l'administration provient d'une IPv4 fixe, créez d'abord une règle restrictive :
sudo ufw allow from 198.51.100.10 to any port 22 proto tcp \
comment 'SSH depuis le poste administration'
sudo ufw status numbered
Après avoir testé depuis cette adresse, supprimez la règle SSH ouverte à tous en utilisant son numéro :
sudo ufw delete NUMERO_DE_LA_REGLE
Répétez la logique pour IPv6 si l'administrateur l'utilise. Ne désactivez pas IPv6 uniquement pour éviter d'écrire ses règles : une adresse AAAA ou une interface IPv6 oubliée peut créer une exposition différente de celle testée en IPv4.
Notre tutoriel configurer UFW sur un VPS Linux détaille la gestion des règles.
Option B : nftables sur un VPS Debian sans Docker
L'exemple ci-dessous convient à un VPS web neuf, non routeur, sans Docker, avec SSH sur 22. Il remplace l'ensemble du ruleset : ne l'utilisez pas si un autre logiciel gère déjà netfilter.
Sauvegardez d'abord l'état actuel dans un fichier qui commencera lui-même par une remise à zéro du ruleset :
sudo sh -c '{
printf "%s\n" "flush ruleset"
nft list ruleset
} > /root/nftables.before-hardening.nft'
sudoedit /etc/nftables.conf
Contenu :
#!/usr/sbin/nft -f
flush ruleset
define ssh_port = 22
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iifname "lo" accept
ct state invalid drop
ct state established,related accept
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
tcp dport $ssh_port ct state new accept comment "SSH"
tcp dport { 80, 443 } ct state new accept comment "Web"
counter drop
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Laisser ICMP et ICMPv6 utiles évite de casser la découverte de voisinage IPv6, le diagnostic et la découverte de la MTU. Ne recopiez pas une règle qui bloque tout ICMP sans comprendre ces fonctions.
Vérifiez la syntaxe avant d'appliquer :
sudo nft -c -f /etc/nftables.conf
sudo nft -f /etc/nftables.conf
sudo nft list ruleset
sudo systemctl enable nftables
Testez une nouvelle session SSH et le service web. Pour revenir en arrière depuis la console :
sudo nft -f /root/nftables.before-hardening.nft
Le fichier de retour arrière contient lui aussi flush ruleset : son chargement remplace donc la politique courante au lieu d'ajouter des règles en double. Effectuez ce retour depuis la console de secours si SSH est déjà interrompu.
Si le VPS route du trafic, héberge un VPN, utilise plusieurs interfaces ou exécute Docker, concevez les chaînes forward et NAT pour cette architecture. Une politique drop copiée sans adaptation peut interrompre le service.
Ajouter un pare-feu réseau
Lorsque l'hébergeur propose un pare-feu en amont, utilisez-le comme seconde barrière : SSH seulement depuis les adresses d'administration ou le VPN, HTTP/HTTPS depuis Internet si le serveur est public, bases de données et panneaux d'administration jamais ouverts à tous, règles IPv4 et IPv6 cohérentes, console de secours testée.
Le filtrage amont peut bloquer un trafic avant qu'il ne consomme les ressources du VPS. Il ne voit toutefois pas forcément les réseaux internes aux conteneurs et ne protège pas un service accessible depuis le VPS lui-même.
6. Cas critique : Docker et les règles UFW ou nftables
Docker modifie les règles de filtrage et de NAT pour publier les ports des conteneurs. Sa documentation avertit que le trafic d'un port publié est détourné avant les chaînes INPUT et OUTPUT utilisées par UFW ; un port Docker peut donc rester accessible malgré une politique UFW qui semble le refuser. Consultez la page officielle Packet filtering and firewalls.
Inventoriez les publications :
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'
sudo ss -lntup
sudo iptables -S DOCKER-USER 2>/dev/null
Différence essentielle :
# Exposé sur toutes les interfaces du VPS
ports:
- "8080:80"
# Accessible uniquement depuis le VPS, par exemple via Nginx
ports:
- "127.0.0.1:8080:80"
Pour une base, Redis, un panneau ou une application derrière un reverse proxy, liez le port à 127.0.0.1 ou à une adresse privée lorsque l'accès public n'est pas nécessaire.
Docker recommande d'utiliser la chaîne DOCKER-USER pour les politiques qui doivent précéder ses propres règles iptables. Il déconseille de désactiver sa gestion iptables/ip6tables, car cela casse généralement le réseau des conteneurs. La documentation d'installation Docker précise en outre que Docker Engine prend en charge iptables-nft et iptables-legacy, mais pas un ruleset créé directement avec nft comme mécanisme de filtrage Docker. Ne mélangez donc pas le modèle nftables précédent avec Docker sans architecture testée. Notre guide installer Docker sur un VPS Linux couvre l'installation et la configuration du démon.
Après chaque déploiement de conteneur, refaites un scan depuis un réseau extérieur. Le fichier Compose décrit l'intention ; le réseau observable décrit la réalité.
7. Réduire les services, paquets et privilèges
Listez les unités actives et les ports :
sudo systemctl --type=service --state=running --no-pager
sudo systemctl list-unit-files --state=enabled --no-pager
sudo ss -lntup
Pour chaque service, demandez : est-il indispensable ? doit-il démarrer automatiquement ? doit-il écouter sur une interface publique ? fonctionne-t-il avec un compte dédié non privilégié ? de quels fichiers, capacités Linux et réseaux a-t-il besoin ? son journal et son état sont-ils surveillés ?
Arrêter puis désactiver est plus prudent que supprimer immédiatement :
sudo systemctl disable --now NOM_DU_SERVICE
sudo systemctl status NOM_DU_SERVICE --no-pager
Après une période d'observation et une vérification des dépendances, supprimez le paquet si son absence est confirmée.
Ne pas exécuter l'application en root
Un service applicatif doit utiliser un compte système dédié, des répertoires limités et aucun shell interactif si celui-ci n'est pas requis. Les bases de données doivent écouter sur loopback ou une adresse privée, sauf besoin explicite et filtré.
Avec systemd, analysez d'abord le niveau de cloisonnement :
sudo systemd-analyze security --no-pager NOM.service
sudo systemctl cat NOM.service
Le score de systemd-analyze security mesure uniquement les protections systemd connues de l'outil. Un score élevé n'est pas la preuve d'une vulnérabilité, et un score faible ne valide pas le code de l'application. Le manuel systemd-analyze insiste sur cette limite.
Pour une application interne non JIT qui écrit seulement dans deux répertoires, un drop-in peut ressembler à :
[Service]
User=myapp
Group=myapp
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
LockPersonality=yes
CapabilityBoundingSet=
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadWritePaths=/var/lib/myapp /var/log/myapp
Créez-le avec :
sudo systemctl edit NOM.service
sudo systemd-analyze verify NOM.service
sudo systemctl daemon-reload
sudo systemctl restart NOM.service
sudo systemctl status NOM.service --no-pager
sudo journalctl -u NOM.service -n 100 --no-pager
Appliquez les options une par une. MemoryDenyWriteExecute=yes, ProtectHome=yes, la restriction des familles d'adresses ou la suppression des capacités peuvent casser un runtime JIT, un binaire qui charge des modules ou un service qui attend un accès particulier. La référence complète est systemd.exec.
8. Conserver et contrôler AppArmor
AppArmor applique un contrôle d'accès obligatoire par programme. Sur Ubuntu, il est installé et chargé par défaut. Vérifiez son état :
sudo aa-status
systemctl status apparmor --no-pager
La documentation AppArmor d'Ubuntu distingue notamment le mode enforce, qui bloque les opérations interdites et les journalise, le mode complain, utile pour apprendre un profil sans bloquer, et les processus confinés ou sans profil.
Sur Debian, AppArmor est disponible mais son activation et la présence de profils dépendent de l'image et du noyau :
sudo apt install apparmor apparmor-utils
sudo systemctl enable --now apparmor
sudo aa-status
Ne désactivez pas AppArmor pour « corriger » une application. Analysez les refus :
sudo journalctl -k -g 'apparmor="DENIED"' --since today
Créez ou adaptez un profil en préproduction, passez temporairement le profil concerné en apprentissage si nécessaire, puis revenez en enforce. Un profil trop permissif ou laissé en complain ne fournit pas la protection attendue.
9. Ajouter Fail2ban lorsque le service le justifie
Fail2ban lit les événements d'échec et ajoute temporairement une règle de blocage. Il réduit le bruit et certaines attaques répétées, mais ne corrige ni un mot de passe faible, ni une faille logicielle, ni un identifiant volé.
Installez-le :
sudo apt update
sudo apt install fail2ban
sudoedit /etc/fail2ban/jail.d/sshd.local
Configuration pour un système utilisant le journal systemd :
[sshd]
enabled = true
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
Le backend systemd lit le journal et ne doit pas recevoir un logpath. Les paramètres et unités de temps sont décrits dans le manuel Debian jail.conf.
Validez avant le démarrage :
sudo fail2ban-client -t
sudo systemctl enable --now fail2ban
sudo fail2ban-client ping
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo journalctl -u fail2ban -n 100 --no-pager
Une liste blanche n'est raisonnable que pour une adresse réellement stable et maîtrisée. Une plage trop large contourne précisément le contrôle que vous venez d'ajouter. Avec Docker, vérifiez aussi que l'action choisie agit dans la chaîne réellement traversée par le trafic.
Notre guide installer et configurer Fail2ban traite les journaux Debian récents, la jail SSH, le débannissement et les tests de filtres.
10. Durcir prudemment quelques paramètres du noyau
Les sysctl ne doivent pas être copiés par centaines depuis une checklist générique. Le noyau Linux prévient que certains réglages peuvent rendre un système inutilisable et recommande de comprendre chaque ajustement.
Commencez par relever les valeurs :
sysctl kernel.dmesg_restrict
sysctl kernel.kptr_restrict
sysctl fs.protected_hardlinks
sysctl fs.protected_symlinks
sysctl fs.protected_fifos
sysctl fs.protected_regular
sysctl net.ipv4.conf.all.accept_redirects
sysctl net.ipv6.conf.all.accept_redirects
Pour un VPS hôte classique, non routeur, ce fragment conservateur peut être étudié :
sudoedit /etc/sysctl.d/60-local-hardening.conf
# Limiter l'exposition d'informations du noyau
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
# Renforcer les objets créés dans les répertoires temporaires partagés
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2
# Un VPS hôte n'a normalement pas besoin d'accepter les redirections ICMP
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# Il n'a normalement pas besoin d'émettre des redirections IPv4
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
Chargez puis contrôlez :
sudo sysctl -p /etc/sysctl.d/60-local-hardening.conf
sudo sysctl --system
La documentation du noyau détaille les sysctl IP et les sysctl de fichiers.
Ce guide ne force volontairement pas net.ipv4.ip_forward=0, car Docker, WireGuard ou un routeur peuvent en dépendre ; ni rp_filter=1, car le routage asymétrique, certains VPN et le policy routing exigent une étude ; ni la désactivation d'IPv6 ; ni la désactivation irréversible des modules ou de kexec ; ni un réglage BPF ou io_uring sans inventaire des applications et agents.
11. Rendre les journaux persistants et exploitables
Les journaux locaux sont utiles pour le diagnostic, mais un attaquant devenu root peut les modifier ou les effacer. La stratégie doit combiner conservation locale bornée, horloge fiable, transfert distant et alertes.
Persistance et limite d'espace de journald
Créez un fragment :
sudo install -d -m 755 /etc/systemd/journald.conf.d
sudoedit /etc/systemd/journald.conf.d/60-persistent.conf
Exemple à adapter à la taille du disque :
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=30day
Puis :
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
sudo journalctl --flush
sudo journalctl --disk-usage
sudo journalctl --verify
sudo journalctl -p warning..alert --since today
SystemMaxUse, SystemKeepFree et la persistance sont documentés dans journald.conf. Une limite fixe doit laisser suffisamment d'espace au système et à l'application.
Centraliser les traces hors du VPS
Pour un serveur de production, transférez au minimum les authentifications SSH et sudo, les événements du noyau et du pare-feu, les changements d'identité, les journaux du reverse proxy et de l'application, ainsi que les mises à jour automatiques, sauvegardes et agents de sécurité.
Deux solutions courantes sont systemd-journal-upload vers systemd-journal-remote, ou rsyslog vers un collecteur. systemd-journal-upload envoie les entrées de journal ; le module omfwd de rsyslog prend en charge UDP, TCP ou TLS et recommande TCP avec TLS pour un déploiement moderne.
Une mise en œuvre sérieuse doit authentifier le collecteur par certificat, vérifier son nom et son autorité de certification, utiliser TLS plutôt qu'un syslog UDP en clair sur Internet, mettre en file d'attente les événements pendant une coupure, empêcher le VPS source d'effacer les archives du collecteur, alerter si le flux ou le heartbeat s'interrompt, et protéger les journaux contre les accès non autorisés, car ils contiennent souvent des données sensibles.
Synchroniser l'heure
timedatectl status
timedatectl timesync-status 2>/dev/null || true
systemctl status systemd-timesyncd chrony --no-pager 2>/dev/null || true
Utilisez un seul mécanisme de synchronisation correctement configuré. Une dérive horaire complique la corrélation des événements, les certificats, les jetons et parfois l'authentification.
12. Auditer les changements et l'intégrité
Linux Audit
auditd collecte des événements produits par le sous-système d'audit du noyau. Debian fournit les outils pour stocker et rechercher ces enregistrements, documentés dans les manuels auditd de Debian 13.
sudo apt install auditd audispd-plugins
sudo systemctl enable --now auditd
sudoedit /etc/audit/rules.d/50-local.rules
Socle minimal :
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/sudoers -p wa -k privilege
-w /etc/sudoers.d -p wa -k privilege
-w /etc/ssh/sshd_config -p wa -k ssh_config
-w /etc/ssh/sshd_config.d -p wa -k ssh_config
Chargez et vérifiez :
sudo augenrules --check
sudo augenrules --load
sudo auditctl -s
sudo auditctl -l
sudo ausearch -k ssh_config -ts today -i
sudo aureport --auth --summary
Adaptez les règles aux fichiers réellement critiques. Un audit excessif remplit le disque et rend le signal inexploitable. Configurez la rotation, l'alerte de saturation et le transfert distant.
Vérification des paquets et AIDE
Pour relever les fichiers de paquets modifiés :
sudo dpkg -V
Une sortie n'est pas automatiquement une compromission : des fichiers de configuration sont légitimement modifiés. Comparez-les à votre gestion de configuration et à vos changements approuvés.
AIDE construit une base d'intégrité :
sudo apt install aide
sudo aideinit
sudo aide --check
Initialisez la base seulement sur un serveur réputé propre et après le durcissement. Lisez le résultat d'aideinit pour confirmer quelle base est active sur votre distribution. Copiez la base de référence ou au minimum son empreinte vers un emplacement protégé hors du VPS ; sinon un attaquant root peut modifier à la fois les fichiers et leur référence.
Ni auditd ni AIDE ne sont un EDR complet. Ils ajoutent des traces et des contrôles d'intégrité, à condition que les résultats soient lus et protégés.
13. Protéger les fichiers, clés et secrets
Recherchez les anomalies sans les corriger automatiquement :
sudo find /etc -xdev -type f -perm -0002 -ls
sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -print
sudo find /root /home -path '*/.ssh/authorized_keys' -type f \
-exec stat -c '%a %U:%G %n' {} \;
sudo find /etc/cron.d /etc/cron.daily /etc/cron.hourly \
/etc/cron.monthly /etc/cron.weekly /var/spool/cron \
-maxdepth 2 -type f -ls 2>/dev/null
systemctl list-timers --all --no-pager
Une permission inhabituelle n'est pas nécessairement malveillante. Identifiez le paquet, le propriétaire et l'usage avant de modifier.
Règles de base : aucun secret dans Git, une image Docker, une commande visible dans l'historique ou une URL ; fichiers de secrets lisibles seulement par le compte nécessaire ; jetons distincts par service et par environnement ; privilèges minimaux côté DNS, sauvegarde, base et API ; rotation planifiée et immédiate après exposition ; suppression des anciens authorized_keys ; clés privées jamais copiées dans une documentation ou un ticket.
Pour les services systemd modernes, étudiez les credentials systemd plutôt que des variables d'environnement globales. Une variable reste parfois visible par des processus privilégiés et peut finir dans un diagnostic.
14. Chiffrer les services publics avec TLS
HTTPS protège le trafic entre le client et le serveur ; il ne corrige pas une application vulnérable. Pour un site Nginx ou Apache, le DNS A et, s'il existe, AAAA doivent pointer vers le bon serveur ; les ports TCP 80 et 443 doivent être ouverts selon le challenge ACME ; le renouvellement doit être automatisé et testé ; une alerte doit précéder l'expiration ; HSTS ne doit être activé qu'après validation durable de HTTPS sur les noms concernés.
Suivez notre guide Certbot : installer un SSL Let's Encrypt sur VPS, puis vérifiez :
sudo certbot certificates
sudo certbot renew --dry-run
systemctl list-timers '*certbot*' --all
openssl s_client \
-connect example.com:443 \
-servername example.com \
-verify_return_error </dev/null
Une redirection HTTP vers HTTPS est utile pour le navigateur, mais gardez le port 80 accessible si le renouvellement HTTP-01 en dépend. DNS-01 est nécessaire pour un wildcard et peut éviter cette dépendance, au prix d'un secret API DNS à protéger.
15. Mettre en place une sauvegarde réellement restaurable
L'ANSSI rappelle que les sauvegardes sont indispensables face aux incidents et recommande notamment une politique 3-2-1 : trois copies, sur deux supports différents, dont une hors ligne. Elle demande aussi de formaliser la perte de données maximale admissible et la durée d'interruption maximale admissible dans son référentiel de mesures et son guide Sauvegarde des systèmes d'information.
Distinguer archive, snapshot et sauvegarde
| Mécanisme | Utile pour | Limite |
|---|---|---|
| archive tar sur le même disque | copie ponctuelle de fichiers | disparaît avec le VPS ou le disque |
| snapshot du VPS | retour arrière rapide avant changement | même compte fournisseur, cohérence applicative à vérifier |
| réplication ou synchronisation | disponibilité ou copie rapide | réplique aussi l'effacement et la corruption |
| sauvegarde versionnée hors site | reprise après panne, erreur ou compromission | doit être chiffrée, supervisée et restaurée |
| copie hors ligne ou immuable | résistance à l'effacement et au rançongiciel | exige une politique de rétention et des tests |
Nos VPS proposent en option des sauvegardes délocalisées automatiques : une copie complète du VPS, réalisée chaque jour, stockée dans un datacenter européen distinct, avec restauration en un clic et un historique rotatif dont vous choisissez la profondeur. Dix sauvegardes simultanées correspondent ainsi à dix jours d'historique, chaque nouvelle copie remplaçant la plus ancienne. Cette option couvre déjà la copie hors du serveur, la fréquence quotidienne et la restauration rapide.
Elle ne dispense pas pour autant des deux précautions suivantes. D'abord, la copie complète d'un VPS en fonctionnement n'est pas forcément cohérente pour une base de données : continuez à produire un dump juste avant, comme décrit plus bas. Ensuite, elle reste pilotée depuis le même compte fournisseur que le serveur ; pour le scénario de compromission, conservez en complément une copie dans un domaine d'administration distinct, en append-only ou hors ligne selon le risque. Et dans tous les cas, testez la restauration : un historique de dix jours n'a de valeur que si vous avez vérifié qu'une restauration redémarre réellement l'application.
Définir l'objectif avant l'outil
| Donnée | RPO/PDMA | RTO/DMIA | Rétention |
|---|---|---|---|
| configuration système | 24 h | 4 h | 30 jours |
| fichiers clients | 1 h | 2 h | 30 jours et 12 mois |
| base transactionnelle | 15 min | 1 h | journaux et sauvegardes quotidiennes |
| journaux de sécurité | selon politique | consultation immédiate | 90 jours ou exigence applicable |
Ces valeurs dictent la fréquence et la technologie. Une sauvegarde quotidienne ne satisfait pas un RPO de quinze minutes.
Exemple avec restic vers une destination distante
restic chiffre et déduplique les sauvegardes. Il prend en charge plusieurs backends ; l'exemple utilise SFTP. Installez le paquet de la distribution :
sudo apt update
sudo apt install restic
sudo install -d -m 700 /root/.config/restic
sudo touch /root/.config/restic/password
sudo chown root:root /root/.config/restic/password
sudo chmod 600 /root/.config/restic/password
sudoedit /root/.config/restic/password
sudo touch /etc/restic-vps.env
sudo chown root:root /etc/restic-vps.env
sudo chmod 600 /etc/restic-vps.env
sudoedit /etc/restic-vps.env
Contenu de /etc/restic-vps.env :
RESTIC_REPOSITORY=sftp:backup@backup.example:/srv/restic/vps-01
RESTIC_PASSWORD_FILE=/root/.config/restic/password
La phrase secrète doit être longue, aléatoire, conservée dans un gestionnaire distinct et testée. Sans elle, le dépôt chiffré n'est pas restaurable.
Initialisez manuellement depuis une session root après avoir validé l'empreinte SSH du serveur de sauvegarde :
sudo -i
set -a
. /etc/restic-vps.env
set +a
restic init
restic backup /etc /srv /var/www /var/backups/databases
restic snapshots
restic check
exit
La sauvegarde d'un répertoire de données de base en activité n'est pas forcément cohérente. Produisez un dump ou utilisez la méthode physique et les journaux recommandés par le moteur.
Pour MariaDB, lorsque l'authentification locale root par socket est configurée :
sudo install -d -m 700 /var/backups/databases
sudo sh -c 'mariadb-dump --single-transaction --routines --events --triggers --all-databases | gzip -9 > "/var/backups/databases/mariadb-$(date -u +%F-%H%M%S).sql.gz"'
Pour PostgreSQL :
sudo install -d -m 700 -o postgres -g postgres \
/var/backups/databases/postgresql
sudo -u postgres sh -c 'pg_dumpall | gzip -9 > "/var/backups/databases/postgresql/all-$(date -u +%F-%H%M%S).sql.gz"'
Testez la restauration sur une base isolée. --single-transaction améliore la cohérence des tables transactionnelles MariaDB/InnoDB, mais n'est pas une garantie universelle pour tous les moteurs et toutes les opérations.
Automatiser avec un timer systemd
Créez /etc/systemd/system/restic-backup.service :
[Unit]
Description=Sauvegarde restic du VPS
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic-vps.env
ExecStart=/usr/bin/restic backup /etc /srv /var/www /var/backups/databases
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
Créez /etc/systemd/system/restic-backup.timer :
[Unit]
Description=Sauvegarde quotidienne restic du VPS
[Timer]
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
Activez et contrôlez :
sudo systemd-analyze verify \
/etc/systemd/system/restic-backup.service \
/etc/systemd/system/restic-backup.timer
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
sudo systemctl start restic-backup.service
sudo systemctl status restic-backup.service --no-pager
sudo journalctl -u restic-backup.service -n 100 --no-pager
systemctl list-timers restic-backup.timer --all
Le dump de base doit être produit juste avant ce service, par une unité dédiée ordonnée avec Requires et After, ou par un orchestrateur de sauvegarde. Un vieux dump sauvegardé chaque nuit donne une illusion de fraîcheur.
Séparer écriture et suppression
Un VPS compromis ne devrait pas pouvoir effacer les anciennes sauvegardes. Lorsque le backend le permet, donnez au VPS un accès append-only. Exécutez la rétention depuis une machine d'administration distincte qui possède les droits de suppression :
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune
restic check --read-data-subset=5%
La documentation restic sur forget et prune précise que prune peut être long, verrouille le dépôt et doit être planifié. Elle recommande aussi un contrôle après l'élagage. Pour un dépôt append-only, étudiez les risques particuliers des politiques de rétention et séparez réellement le client de maintenance.
Tester une restauration
Au moins chaque trimestre, sur une machine isolée :
sudo -i
set -a
. /etc/restic-vps.env
set +a
restic snapshots
install -d -m 700 /mnt/restic-restore-test
restic restore latest --target /mnt/restic-restore-test
exit
Vérifiez ensuite la présence et les droits des fichiers, le déchiffrement avec les identifiants documentés, la restauration des bases dans un moteur de test, le démarrage de l'application, la cohérence fonctionnelle, le temps réel de restauration comparé au RTO et la procédure de reconstruction d'un VPS vierge.
Une sauvegarde « réussie » signifie que le processus a terminé. Une sauvegarde fiable signifie qu'une restauration utile a été démontrée.
16. Superviser le VPS depuis l'extérieur
La supervision locale ne peut pas signaler un VPS éteint, isolé ou totalement compromis. Utilisez un service externe pour la disponibilité et un canal d'alerte distinct du serveur.
| Contrôle | Signal à surveiller |
|---|---|
| disponibilité | TCP/HTTPS, contenu attendu, latence |
| TLS | date d'expiration, chaîne et nom |
| système | CPU, mémoire, swap, charge |
| stockage | espace, inodes, croissance des journaux |
| services | unités systemd en échec, redémarrages |
| réseau | nouveaux ports, connexions inhabituelles |
| sécurité | échecs SSH, sudo, refus AppArmor, auditd |
| correctifs | dernière exécution, échec, redémarrage requis |
| sauvegardes | âge du dernier snapshot, taille anormale, échec |
| temps | dérive ou perte de synchronisation |
Commandes de contrôle quotidien :
systemctl --failed --no-pager
df -hT
df -ih
free -h
uptime
sudo ss -lntup
sudo journalctl -p warning..alert --since '-24 hours'
sudo journalctl -u ssh --since '-24 hours'
sudo fail2ban-client status sshd 2>/dev/null || true
sudo aa-status 2>/dev/null || true
Les seuils doivent refléter le service. Une alerte à 80 % de disque n'est utile que si elle arrive assez tôt par rapport à la vitesse de croissance. Alertez aussi sur l'absence de données : un agent silencieux peut être en panne.
L'ANSSI définit la supervision de sécurité comme l'ensemble des moyens permettant de détecter, qualifier et choisir une réaction adaptée ; son guide Piloter un projet de supervision replace les outils dans ce processus.
17. Vérifier le résultat au lieu de faire confiance à la configuration
Contrôles locaux
# Système et correctifs
cat /etc/os-release
apt list --upgradable
systemctl list-timers 'apt-daily*' --all
# SSH effectif
sudo sshd -t
sudo sshd -T | grep -E '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|allowgroups) '
# Exposition réseau
sudo ss -lntup
sudo ufw status verbose 2>/dev/null || true
sudo nft list ruleset 2>/dev/null || true
# Contrôles de sécurité
sudo aa-status 2>/dev/null || true
sudo fail2ban-client status 2>/dev/null || true
sudo auditctl -s 2>/dev/null || true
# Journal et services
sudo journalctl --verify
systemctl --failed --no-pager
# Sauvegarde
sudo systemctl status restic-backup.service --no-pager
Scan externe
Depuis un poste que vous administrez, et uniquement contre votre propre VPS :
sudo nmap -Pn -sS -sV -p- ADRESSE_IPV4_DU_VPS
sudo nmap -6 -Pn -sT -sV -p- ADRESSE_IPV6_DU_VPS
Comparez le résultat à la liste des ports autorisés. La référence des options se trouve dans le manuel Nmap.
Effectuez le scan après le premier durcissement, après l'installation de Docker ou d'un panneau, après une modification de pare-feu, après une migration réseau, et régulièrement depuis Internet.
Tableau de recette
| Test | Résultat attendu | Preuve à conserver |
|---|---|---|
| connexion SSH par clé | succès avec compte nominatif | journal SSH anonymisé |
| connexion root SSH | refus | extrait du test |
| mot de passe SSH | refus | commande et résultat |
| sudo | succès pour l'administrateur autorisé | journal sudo |
| syntaxe SSH | sshd -t sans erreur | date et version |
| ports externes | uniquement les flux approuvés | rapport Nmap IPv4 et IPv6 |
| mise à jour automatique | dry-run valide, timer actif | journal |
| pare-feu | politique et règles conformes | export UFW ou nftables |
| AppArmor | actif, profils critiques en enforce | sortie aa-status |
| sauvegarde | exécution sans erreur | journal et snapshot restic |
| restauration | application et données lisibles | procès-verbal daté |
| journaux distants | événement reçu et horodaté | recherche côté collecteur |
| console de secours | connexion possible | date du dernier test |
18. Que faire en cas de suspicion de compromission ?
Des symptômes comme un pic CPU, un processus inconnu ou une connexion sortante inhabituelle justifient une qualification, mais ne prouvent pas seuls une intrusion. À l'inverse, l'absence de symptôme ne prouve pas l'intégrité.
Premières actions, à adapter à la gravité :
- utilisez un poste de confiance et ouvrez un journal d'incident ;
- isolez le VPS avec le pare-feu réseau lorsque cela ne détruit pas les preuves ;
- évitez de redémarrer ou de « nettoyer » avant la collecte si une investigation est prévue ;
- préservez les journaux distants, l'état des processus, les connexions, les tâches et un snapshot forensique ;
- révoquez depuis un système sain les clés SSH, mots de passe, jetons, certificats et accès fournisseur exposés ;
- protégez les sauvegardes antérieures et empêchez leur suppression ;
- déterminez le périmètre : autres VPS, dépôt Git, CI/CD, DNS, comptes et bases ;
- reconstruisez depuis une image et une configuration réputées saines ;
- restaurez uniquement des données contrôlées ;
- corrigez la cause avant la remise en ligne et renforcez la surveillance.
Un snapshot du serveur suspect sert à préserver ou analyser un état ; il ne devient pas automatiquement un point de restauration sain. Le CERT-FR recommande notamment de conserver les preuves, limiter l'extension, mettre les sauvegardes en sécurité et remplacer un système compromis par un système neuf ou réinstallé. Consultez Les bons réflexes en cas d'intrusion.
Le NIST SP 800-61 révision 3, publié en avril 2025, intègre la réponse à incident dans l'ensemble de la gestion du risque : préparation, détection, réponse et récupération ne commencent pas le jour de l'attaque.
Calendrier d'exploitation recommandé
| Fréquence | Actions |
|---|---|
| en continu | disponibilité externe, métriques, alertes sécurité, échecs de sauvegarde |
| quotidien | mises à jour de sécurité, sauvegarde, vérification des services en échec |
| hebdomadaire | revue des alertes, ports, espace, comptes et changements |
| mensuel | revue des dépôts, paquets, clés, règles de pare-feu et versions |
| trimestriel | restauration complète testée, console de secours, exercice d'incident |
| semestriel | revue d'architecture, privilèges, RPO/RTO et exposition externe |
| à chaque changement | sauvegarde, validation, scan externe, documentation et retour arrière |
Pour plusieurs VPS, gérez ce socle avec Ansible, un dépôt versionné et une CI qui teste la syntaxe. Les secrets doivent rester hors du dépôt. Une configuration déclarative ne remplace pas les tests sur l'environnement réel, mais elle rend les écarts et les retours arrière plus contrôlables.
Erreurs fréquentes
- Fermer SSH avant d'avoir testé la clé. Gardez une session et la console fournisseur.
- Ouvrir UFW pour le port 22 alors que SSH écoute ailleurs. Vérifiez
sshd -T. - Nommer un fragment SSH tardif. La première valeur gagne souvent ; contrôlez la configuration effective.
- Oublier IPv6. Scannez et filtrez séparément IPv4 et IPv6.
- Croire qu'UFW filtre automatiquement Docker. Les ports publiés exigent un contrôle spécifique.
- Installer Fail2ban sans vérifier la jail. Contrôlez
status sshdet les journaux. - Activer un sysctl générique. Un réglage réseau peut casser VPN, routage ou conteneurs.
- Sauvegarder sur le même disque. Une panne ou une compromission emporte l'original et la copie.
- Ne jamais restaurer. Un job vert ne garantit ni le mot de passe, ni la cohérence, ni le délai.
- Garder tous les journaux localement. Root peut les effacer ; transférez les événements critiques.
- Exécuter l'application en root. Une faille applicative devient immédiatement une compromission système.
- Confondre version amont et statut de CVE. Vérifiez le tracker de la distribution.
Questions fréquentes
Changer le port SSH sécurise-t-il le VPS ?
Cela réduit le bruit des scans opportunistes et la taille des journaux, mais n'ajoute pas une barrière d'authentification. Une clé protégée, un compte non-root, la restriction réseau et les correctifs sont prioritaires.
Fail2ban est-il encore utile si les mots de passe SSH sont désactivés ?
Il peut réduire le bruit et certaines tentatives répétées. Son importance diminue si SSH est accessible uniquement par VPN ou depuis une liste d'adresses, mais il ne remplace aucune de ces mesures.
Faut-il installer un antivirus sur Linux ?
La réponse dépend du service. ClamAV peut analyser des fichiers téléversés ou une messagerie. Un agent EDR peut apporter télémétrie et réponse sur un serveur sensible. Aucun antivirus ne compense un système non corrigé, une application root ou des secrets exposés.
UFW ou nftables ?
UFW est adapté à une politique simple et constitue l'outil par défaut documenté par Ubuntu. nftables est le framework natif recommandé par Debian et offre davantage de contrôle. Choisissez un propriétaire unique du ruleset et tenez compte de Docker.
Peut-on désactiver IPv6 ?
Ce n'est pas une mesure générique de durcissement. Filtrez et surveillez IPv6 comme IPv4. Désactiver IPv6 peut casser des dépendances et masquer une mauvaise compréhension du réseau.
Un snapshot de l'hébergeur suffit-il ?
Un snapshot est précieux pour un retour arrière rapide, mais il reste généralement dans le même domaine d'administration et sa cohérence applicative doit être vérifiée. Conservez aussi une sauvegarde versionnée hors site, avec une copie hors ligne ou immuable selon le risque. Nos sauvegardes délocalisées en option vont plus loin qu'un simple snapshot, puisqu'elles sont quotidiennes et stockées dans un autre datacenter, mais elles restent pilotées depuis votre compte client : contre le risque de compromission, gardez une copie dans un domaine d'administration distinct.
Comment savoir si le VPS est compromis ?
Il n'existe pas de commande unique. Corrélez les connexions, processus, comptes, clés, tâches, journaux distants, modifications de fichiers, trafic et alertes. En cas de doute sérieux, préservez les preuves, révoquez les secrets et reconstruisez depuis une base saine.
Les mises à jour automatiques peuvent-elles casser la production ?
Tout changement comporte un risque. Le risque de ne pas appliquer un correctif est souvent supérieur, mais une application critique exige préproduction, fenêtres de maintenance, blocage ciblé si justifié, supervision et retour arrière. Ubuntu précise que unattended-upgrades n'est pas un outil complet de gestion de flotte.
Ce guide rend-il le VPS conforme à l'ANSSI ou à CIS ?
Non. Il s'appuie sur des principes et sources reconnus, mais une conformité exige un périmètre, un niveau, des preuves, des exceptions et un audit. Les benchmarks doivent être adaptés au rôle du serveur ; les appliquer automatiquement peut interrompre des fonctions légitimes.
Checklist finale
Identités et SSH
- un compte nominatif par administrateur ;
- clés Ed25519 ou FIDO2 protégées ;
sudotesté ;PermitRootLogin noeffectif ;- mot de passe et keyboard-interactive désactivés si non utilisés ;
- groupe SSH autorisé explicitement ;
- configuration validée avec
sshd -tetsshd -T; - console de secours testée.
Système et réseau
- distribution encore maintenue ;
- correctifs installés et automatisation surveillée ;
- dépôts tiers inventoriés ;
- ports IPv4 et IPv6 justifiés ;
- pare-feu local actif ;
- pare-feu réseau configuré si disponible ;
- publications Docker vérifiées depuis Internet ;
- services inutiles désactivés.
Réduction d'impact
- applications sous comptes dédiés ;
- AppArmor actif et refus examinés ;
- services systemd cloisonnés selon leurs besoins ;
- secrets à privilèges minimaux ;
- permissions et clés revues ;
- sysctl adaptés au rôle, sans copie aveugle.
Détection et reprise
- journaux persistants avec limite d'espace ;
- horloge synchronisée ;
- événements critiques envoyés hors du VPS ;
- auditd et AIDE si le risque le justifie ;
- supervision externe et canal d'alerte distinct ;
- sauvegardes chiffrées, versionnées et hors site ;
- droits de suppression séparés ou stockage immuable ;
- restauration réelle testée et chronométrée ;
- procédure d'incident et contacts disponibles hors ligne.
Pour aller plus loin
Ce guide est le socle transversal. Les procédures détaillées se trouvent dans nos guides dédiés : configurer une clé SSH, configurer UFW, installer Fail2ban, installer Docker et installer un certificat Let's Encrypt avec Certbot. Si vous arrivez d'un hébergement mutualisé, notre guide migrer un site vers un VPS décrit la bascule complète.
Sources principales
Recommandations générales
- ANSSI : recommandations de configuration d'un système GNU/Linux
- ANSSI : sauvegarde des systèmes d'information
- CERT-FR : les bons réflexes en cas d'intrusion
- NIST SP 800-61 Rev. 3 : Incident Response Recommendations
Debian et Ubuntu
- Debian 13 « trixie »
- Debian Administrator's Handbook
- Debian : nftables
- Ubuntu : cycle de vie
- Ubuntu Server : OpenSSH
- Ubuntu Server : firewalls
- Ubuntu Server : AppArmor
- Ubuntu Server : mises à jour automatiques
