Linux•29 août 2026• 175 vues

Sécuriser un VPS Linux en 2026 : guide de durcissement Debian et Ubuntu

Sécuriser un VPS Linux en 2026 : guide de durcissement Debian et Ubuntu

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èmeSituation au 31 août 2026Décision conseillée
Debian 13stable actuellechoix Debian recommandé pour une nouvelle installation
Debian 12LTS, support plus limité selon l'architectureplanifier la migration vers Debian 13
Ubuntu 26.04 LTSLTS actuellechoix Ubuntu recommandé après validation de la compatibilité applicative
Ubuntu 24.04 LTSmaintenance standard jusqu'en 2029excellent choix pour une pile déjà qualifiée
Ubuntu 22.04 LTSmaintenance standard jusqu'en 2027prévoir la montée de version
version en fin de supportplus de correctifs normauxmigrer ; 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é

NiveauMesures minimalesUsage
Socleinventaire, mises à jour, compte nominatif, clé SSH, root et mot de passe SSH désactivés, pare-feu, sauvegarde distantetout VPS exposé
Productionmises à jour supervisées, AppArmor, Fail2ban selon le risque, journaux persistants et distants, alertes externes, restauration testéesite 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éclarativedonné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 :

  1. vérifiez que la console de secours de l'hébergeur fonctionne ;
  2. conservez la session SSH actuelle ouverte ;
  3. ouvrez une seconde fenêtre pour tester chaque changement ;
  4. relevez l'adresse et le port SSH effectifs ;
  5. créez un snapshot de précaution si la plateforme le permet ;
  6. sauvegardez les fichiers modifiés ;
  7. 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émentValeur à consigner
distribution et versionrésultat de /etc/os-release
noyau et architecturerésultat de uname -a
IPv4 et IPv6 publiquesadresses réellement routées
interface principalenom, adresse, passerelle
ports attenduspar exemple 22, 80 et 443 TCP
services attendusSSH, Nginx, application, agent de supervision
administrateurs autoriséscomptes nominatifs, clés et origine réseau
données critiquesfichiers, bases, secrets et configurations
RPO/PDMAperte de données maximale acceptable
RTO/DMIAduré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 no et AllowAgentForwarding no sont 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-interactive dans 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 :

ContexteChoix conseillé
Ubuntu, règles simplesUFW
Debian, politique native et avancéenftables
Docker Engineétudier d'abord les chaînes et limites Docker
infrastructure avec pare-feu fournisseurappliquer 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écanismeUtile pourLimite
archive tar sur le même disquecopie ponctuelle de fichiersdisparaît avec le VPS ou le disque
snapshot du VPSretour arrière rapide avant changementmême compte fournisseur, cohérence applicative à vérifier
réplication ou synchronisationdisponibilité ou copie rapideréplique aussi l'effacement et la corruption
sauvegarde versionnée hors sitereprise après panne, erreur ou compromissiondoit être chiffrée, supervisée et restaurée
copie hors ligne ou immuablerésistance à l'effacement et au rançongicielexige 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éeRPO/PDMARTO/DMIARétention
configuration système24 h4 h30 jours
fichiers clients1 h2 h30 jours et 12 mois
base transactionnelle15 min1 hjournaux et sauvegardes quotidiennes
journaux de sécuritéselon politiqueconsultation immédiate90 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ôleSignal à surveiller
disponibilitéTCP/HTTPS, contenu attendu, latence
TLSdate d'expiration, chaîne et nom
systèmeCPU, mémoire, swap, charge
stockageespace, inodes, croissance des journaux
servicesunités systemd en échec, redémarrages
réseaunouveaux ports, connexions inhabituelles
sécuritééchecs SSH, sudo, refus AppArmor, auditd
correctifsdernière exécution, échec, redémarrage requis
sauvegardesâge du dernier snapshot, taille anormale, échec
tempsdé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

TestRésultat attenduPreuve à conserver
connexion SSH par clésuccès avec compte nominatifjournal SSH anonymisé
connexion root SSHrefusextrait du test
mot de passe SSHrefuscommande et résultat
sudosuccès pour l'administrateur autoriséjournal sudo
syntaxe SSHsshd -t sans erreurdate et version
ports externesuniquement les flux approuvésrapport Nmap IPv4 et IPv6
mise à jour automatiquedry-run valide, timer actifjournal
pare-feupolitique et règles conformesexport UFW ou nftables
AppArmoractif, profils critiques en enforcesortie aa-status
sauvegardeexécution sans erreurjournal et snapshot restic
restaurationapplication et données lisiblesprocès-verbal daté
journaux distantsévénement reçu et horodatérecherche côté collecteur
console de secoursconnexion possibledate 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é :

  1. utilisez un poste de confiance et ouvrez un journal d'incident ;
  2. isolez le VPS avec le pare-feu réseau lorsque cela ne détruit pas les preuves ;
  3. évitez de redémarrer ou de « nettoyer » avant la collecte si une investigation est prévue ;
  4. préservez les journaux distants, l'état des processus, les connexions, les tâches et un snapshot forensique ;
  5. révoquez depuis un système sain les clés SSH, mots de passe, jetons, certificats et accès fournisseur exposés ;
  6. protégez les sauvegardes antérieures et empêchez leur suppression ;
  7. déterminez le périmètre : autres VPS, dépôt Git, CI/CD, DNS, comptes et bases ;
  8. reconstruisez depuis une image et une configuration réputées saines ;
  9. restaurez uniquement des données contrôlées ;
  10. 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équenceActions
en continudisponibilité externe, métriques, alertes sécurité, échecs de sauvegarde
quotidienmises à jour de sécurité, sauvegarde, vérification des services en échec
hebdomadairerevue des alertes, ports, espace, comptes et changements
mensuelrevue des dépôts, paquets, clés, règles de pare-feu et versions
trimestrielrestauration complète testée, console de secours, exercice d'incident
semestrielrevue d'architecture, privilèges, RPO/RTO et exposition externe
à chaque changementsauvegarde, 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

  1. Fermer SSH avant d'avoir testé la clé. Gardez une session et la console fournisseur.
  2. Ouvrir UFW pour le port 22 alors que SSH écoute ailleurs. Vérifiez sshd -T.
  3. Nommer un fragment SSH tardif. La première valeur gagne souvent ; contrôlez la configuration effective.
  4. Oublier IPv6. Scannez et filtrez séparément IPv4 et IPv6.
  5. Croire qu'UFW filtre automatiquement Docker. Les ports publiés exigent un contrôle spécifique.
  6. Installer Fail2ban sans vérifier la jail. Contrôlez status sshd et les journaux.
  7. Activer un sysctl générique. Un réglage réseau peut casser VPN, routage ou conteneurs.
  8. Sauvegarder sur le même disque. Une panne ou une compromission emporte l'original et la copie.
  9. Ne jamais restaurer. Un job vert ne garantit ni le mot de passe, ni la cohérence, ni le délai.
  10. Garder tous les journaux localement. Root peut les effacer ; transférez les événements critiques.
  11. Exécuter l'application en root. Une faille applicative devient immédiatement une compromission système.
  12. 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 ;
  • sudo testé ;
  • PermitRootLogin no effectif ;
  • mot de passe et keyboard-interactive désactivés si non utilisés ;
  • groupe SSH autorisé explicitement ;
  • configuration validée avec sshd -t et sshd -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

Debian et Ubuntu

Composants