diff --git a/docs/contribuer/markdown.md b/docs/contribuer/markdown.md
index 901a11a..250dfed 100644
--- a/docs/contribuer/markdown.md
+++ b/docs/contribuer/markdown.md
@@ -86,6 +86,19 @@ Une ligne vide crée un nouveau paragraphe.
L'indentation d'une sous-liste est de **quatre espaces**. Avec deux, la liste est
ignorée : c'est l'erreur la plus fréquente.
+### Listes de tâches
+
+Pour une checklist, une paire de crochets suffit — cochée avec un `x` :
+
+```markdown
+- [x] Étape faite
+- [ ] Étape à faire
+```
+
+Les cases sont décoratives : le lecteur ne peut pas les cocher dans son navigateur. Elles
+servent aux procédures qu'on suit une fois, comme la
+[préparation d'un serveur Debian](../technique/serveur-debian-13.md).
+
---
## Liens
@@ -285,6 +298,32 @@ Au-delà de la syntaxe, ce qui rend une page utile :
---
+## Diagrammes
+
+Un schéma se décrit en texte, dans un bloc `mermaid` — le thème le dessine à l'affichage :
+
+````markdown
+```mermaid
+flowchart LR
+ A[Rédiger] --> B[Pull request]
+ B --> C[Relecture]
+ C --> D[En ligne]
+```
+````
+
+```mermaid
+flowchart LR
+ A[Rédiger] --> B[Pull request]
+ B --> C[Relecture]
+ C --> D[En ligne]
+```
+
+La syntaxe complète est documentée sur [mermaid.js.org](https://mermaid.js.org/). Un
+schéma reste plus long à maintenir qu'une liste : réservez-le à ce qu'une phrase explique
+mal, comme un enchaînement d'étapes ou une architecture.
+
+---
+
## Pour aller plus loin
- [Éditeur Markdown en ligne, avec aperçu](https://markdownlivepreview.com/)
diff --git a/docs/technique/serveur-debian-13.md b/docs/technique/serveur-debian-13.md
index f721a8b..1347978 100644
--- a/docs/technique/serveur-debian-13.md
+++ b/docs/technique/serveur-debian-13.md
@@ -1,56 +1,1192 @@
-# Préparation serveur Debian 11
-## Le minimum
-[X] Modification du nom du serveur chez le fournisseur
+---
+description: Préparer un serveur Debian 13 « Trixie » livré par un hébergeur — DNS, nom d'hôte, sources deb822, comptes, SSH par clé, pare-feu, fail2ban, mises à jour automatiques, supervision et sauvegarde.
+---
-- Dans la zone DNS, assignez l'adresse IP du serveur à un nom de domaine complet (FQDN).
+# Préparation d'un serveur Debian 13 (Trixie)
-- Modifiez le reverse DNS pour correspondre au FQDN précédemment spécifié.
+!!! info "État du document"
+ Rédigé le **19/09/2026** pour **Debian 13 « Trixie »**. Il remplace l'ancienne fiche
+ Debian 11 : ce qui a changé est résumé en fin de page.
-[X] Connexion au serveur en tant qu'administrateur
+## Avant de commencer
-[X] Modification du nom du serveur : `sudo hostnamectl set-hostname serveur`, où le terme `serveur` doit être remplacé par le nom de votre serveur (non FQDN).
+Cette procédure part d'une installation minimale de Debian 13 « Trixie » fraîchement livrée par un hébergeur, et s'arrête au moment où le serveur est prêt à recevoir ses services. Comptez 30 à 45 minutes.
-[X] Ajouter le nom du serveur dans le fichier `/etc/hosts` à la ligne `127.0.1.1`, avant les noms déjà renseignés. Notez qu'il y a deux références au nom du serveur, un FQDN et l'autre non FQDN. Vous aurez alors 4 références sur la ligne pour le `127.0.1.1`.
+**Règle d'or** : tant que vous touchez à SSH ou au pare-feu, gardez une **deuxième session SSH ouverte** sur le serveur et ne la fermez jamais. Elle est votre filet de sécurité si une modification vous verrouille dehors.
-[X] Mettez à jour le système avec la commande `sudo apt update; sudo apt upgrade -y`
+Vérifiez avant de commencer que vous disposez d'un **accès de secours hors SSH** : console KVM/VNC, console série ou mode rescue de l'hébergeur. Sans lui, une erreur de pare-feu signifie une réinstallation.
-[X] Installez les programmes suivants `sudo apt install -y vnstat iftop htop nano git`
+### Variables utilisées dans ce document
-[X] Configurer la langue avec la commande `LANG=fr_FR.UTF_8`
+Remplacez systématiquement ces valeurs par les vôtres.
-```bash
-echo "locales locales/default_environment_locale select fr_FR.UTF-8" | sudo debconf-set-selections
-sudo dpkg-reconfigure locales
+| Variable | Exemple | Signification |
+| --- | --- | --- |
+| `SRV` | `web01` | Nom court du serveur (sans domaine) |
+| `FQDN` | `web01.exemple.fr` | Nom complet, celui du DNS et du reverse |
+| `IPV4` | `203.0.113.10` | Adresse IPv4 publique |
+| `IPV6` | `2001:db8::10` | Adresse IPv6 publique, si fournie |
+| `USER` | `alix` | Votre futur compte d'administration |
+| `VENDOR` | `debian` | Compte créé par l'hébergeur, à neutraliser |
+| `SSHPORT` | `2222` | Port SSH final, si vous le déplacez |
-sudo timedatectl set-timezone Europe/Paris
+### Ordre des opérations
+
+L'ordre compte : le DNS se propage pendant que vous travaillez, et le pare-feu ne se ferme qu'une fois le nouvel accès SSH prouvé.
+
+```mermaid
+flowchart LR
+ A[DNS + reverse] --> B[Identité
hostname, hosts]
+ B --> C[Système
MAJ, paquets, locale]
+ C --> D[Compte admin
+ sudo]
+ D --> E[SSH
clés + durcissement]
+ E --> F[Pare-feu
+ fail2ban]
+ F --> G[Automatismes
MAJ, supervision]
+ G --> H[Sauvegarde
+ instantané]
```
-[X] Ajouter un nouvel utilisateur en utilisant la commande `adduser nom`
+## Étape 1 — DNS direct et reverse DNS
-[X] Si nécessaire, accorder des droits supplémentaires à l'utilisateur en éditant le fichier des *sudoers* avec la commande `visudo`
+Faites cette étape en premier : la propagation DNS prend de quelques minutes à quelques heures, et elle tournera pendant que vous configurez le reste. Un reverse DNS cohérent conditionne l'acceptation de vos mails et la lisibilité de vos journaux.
-[X] Se reconnecter avec le nouveau compte
+### 1.1 Enregistrements directs (zone DNS du domaine)
-[X] Désactiver ssh pour l'utilisateur `debian`
+Dans l'interface DNS de votre registrar ou de votre hébergeur, créez :
-## Serveur Web avec ISPConfig
-```bash
-sudo apt install gnupg
-# add key
-wget -q http://packages.sury.org/php/apt.gpg -O- | sudo apt-key add -
-```
+| Type | Nom | Valeur | TTL |
+| --- | --- | --- | --- |
+| `A` | `web01` | `203.0.113.10` | 300 pendant la mise en place, puis 3600 |
+| `AAAA` | `web01` | `2001:db8::10` | idem, si IPv6 fournie |
+
+Un TTL court (300 s) pendant l'installation vous laisse corriger une erreur sans attendre. Remontez-le une fois le serveur stabilisé.
+
+### 1.2 Reverse DNS (PTR)
+
+Le PTR ne se déclare pas dans la zone du domaine, mais **chez le propriétaire de l'adresse IP**, c'est-à-dire votre hébergeur. Cherchez dans son panneau une entrée nommée « reverse », « rDNS » ou « PTR », sur la fiche de l'IP et non sur celle du domaine.
+
+La valeur doit être **exactement le FQDN** déclaré en 1.1 : `web01.exemple.fr`. Faites-le pour l'IPv4 **et** pour l'IPv6 ; un reverse IPv6 manquant est une cause classique de mails rejetés.
+
+### 1.3 Vérification
+
+Depuis votre poste, une fois la propagation faite :
```bash
-# add into sources.list
-sudo echo "deb http://packages.sury.org/php/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/php.list
+dig +short web01.exemple.fr A
+dig +short web01.exemple.fr AAAA
+dig +short -x 203.0.113.10
+dig +short -x 2001:db8::10
```
+Les quatre réponses doivent se refermer sur elles-mêmes : le A pointe vers l'IP, le PTR de cette IP renvoie le même FQDN. C'est ce qu'on appelle un FCrDNS valide (*forward-confirmed reverse DNS*).
+
+> Si `dig` n'est pas installé sur votre poste : `sudo apt install dnsutils` sous Debian/Ubuntu, `brew install bind` sous macOS.
+
+## Étape 2 — Première connexion
+
+Connectez-vous avec le compte fourni par l'hébergeur. Sur les images Debian officielles, c'est `debian` ; d'autres utilisent `admin`, `ubuntu` ou `root`.
+
+```bash
+ssh debian@203.0.113.10
+```
+
+Utilisez l'IP et non le FQDN pour cette première connexion : le DNS n'est peut-être pas encore propagé.
+
+### Vérifier ce qu'on a vraiment reçu
+
+Avant toute modification, prenez trois minutes pour constater l'état initial.
+
+```bash
+cat /etc/os-release # confirme Debian 13 (trixie)
+uname -r # version du noyau
+ip -brief address # interfaces et adresses
+lsblk # disques et partitions
+free -h # RAM et swap
+sudo systemctl list-units --type=service --state=running
+sudo ss -tulpn # ce qui écoute déjà sur le réseau
+```
+
+La dernière commande est la plus instructive : elle montre les services exposés dès la livraison. Tout ce qui écoute sur `0.0.0.0` ou `::` et que vous ne reconnaissez pas mérite une décision explicite — désactiver ou garder.
+
+### Si la connexion est refusée
+
+| Symptôme | Cause fréquente |
+| --- | --- |
+| `Permission denied (publickey)` | La clé publique n'a pas été injectée à la commande, ou mauvais nom d'utilisateur |
+| `Connection refused` | Le serveur n'a pas fini de démarrer, ou SSH écoute sur un autre port |
+| `Connection timed out` | Pare-feu amont côté hébergeur (*security group*, *firewall network*) |
+| `REMOTE HOST IDENTIFICATION HAS CHANGED` | Réinstallation ou réattribution d'IP → `ssh-keygen -R 203.0.113.10` |
+
+## Étape 3 — Nom d'hôte et /etc/hosts
+
+### 3.1 Définir le nom d'hôte
+
+Debian attend ici le **nom court**, pas le FQDN. Le FQDN est reconstitué via `/etc/hosts`.
+
+```bash
+sudo hostnamectl set-hostname web01
+```
+
+Vous pouvez aussi renseigner deux champs purement informatifs, utiles quand on gère plusieurs machines :
+
+```bash
+sudo hostnamectl set-hostname "Front web — Paris" --pretty
+sudo hostnamectl set-chassis vm # ou: server, desktop
+```
+
+### 3.2 Corriger /etc/hosts
+
+C'est ce fichier, et non `hostnamectl`, qui donne au système son FQDN. La règle : sur la ligne `127.0.1.1`, **le FQDN vient en premier, le nom court ensuite**.
+
+```bash
+sudo nano /etc/hosts
+```
+
+Ciblez ce résultat :
+
+```
+127.0.0.1 localhost
+127.0.1.1 web01.exemple.fr web01
+
+# The following lines are desirable for IPv6 capable hosts
+::1 localhost ip6-localhost ip6-loopback
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
+```
+
+Certains hébergeurs pré-remplissent la ligne `127.0.1.1` avec le nom d'usine de la machine. Deux options : le supprimer, ou le laisser **après** vos deux entrées — la ligne compte alors quatre références.
+
+```
+127.0.1.1 web01.exemple.fr web01 vps-1a2b3c.exemple-hebergeur.net vps-1a2b3c
+```
+
+Les deux formes fonctionnent. Supprimer l'ancien nom est plus propre ; le conserver évite de casser un script de l'hébergeur qui s'y référerait encore.
+
+> ⚠️ Ne touchez jamais à la ligne `127.0.0.1 localhost`. Et n'associez pas le FQDN à l'IP publique dans `/etc/hosts` : sur une machine à IP dynamique ou derrière NAT, cela crée des résolutions fantomatiques.
+
+### 3.3 Vérifier
+
+```bash
+hostname # → web01
+hostname -f # → web01.exemple.fr
+hostname -d # → exemple.fr
+hostnamectl status
+```
+
+Si `hostname -f` répond autre chose que le FQDN attendu, la ligne `127.0.1.1` est mal ordonnée. Le changement est immédiat, mais reconnectez-vous pour que l'invite de commande l'affiche.
+
+> Sur certaines images cloud, `cloud-init` réécrit le nom d'hôte à chaque redémarrage. Si votre nom revient à sa valeur d'origine après un `reboot` :
+>
+> ```bash
+> sudo sed -i 's/^preserve_hostname:.*/preserve_hostname: true/' /etc/cloud/cloud.cfg
+> grep preserve_hostname /etc/cloud/cloud.cfg
+> ```
+>
+> Ajoutez la ligne si elle est absente.
+
+## Étape 4 — Sources APT et mise à jour
+
+### 4.1 Passer les sources au format deb822
+
+Debian 13 introduit le format deb822 pour les dépôts. L'ancien format une-ligne est officiellement déprécié, même s'il restera supporté par Debian 14 « Forky » ([détail du changement](https://dev.to/r3m8/debian-13-trixie-adoptez-le-nouveau-format-deb822-1ml6)). Autant partir sur le bon format tout de suite.
+
+```bash
+sudo apt modernize-sources
+```
+
+La commande convertit `/etc/apt/sources.list` vers `/etc/apt/sources.list.d/debian.sources` et laisse au passage des sauvegardes `/etc/apt/sources.list.bak` et `/etc/apt/sources.list.save`, ce qui permet de revenir en arrière ([procédure détaillée](https://ostechnix.com/migrate-to-deb822-format-debian-13-trixie/)).
+
+Vérifiez le résultat :
+
+```bash
+cat /etc/apt/sources.list.d/debian.sources
+```
+
+Vous devez y trouver trois blocs : `trixie`, `trixie-updates` et `trixie-security`, chacun avec un champ `Signed-By`.
+
+```
+Types: deb
+URIs: http://deb.debian.org/debian/
+Suites: trixie trixie-updates
+Components: main contrib non-free-firmware
+Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
+
+Types: deb
+URIs: http://security.debian.org/debian-security/
+Suites: trixie-security
+Components: main contrib non-free-firmware
+Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
+```
+
+> Si le dépôt `trixie-security` manque, ajoutez-le à la main : sans lui, vous ne recevez aucun correctif de sécurité. C'est l'erreur la plus coûteuse de toute cette procédure.
+
+`non-free-firmware` est nécessaire sur matériel physique (cartes réseau, RAID). `contrib` et `non-free` sont optionnels ; ne les ajoutez que si un paquet précis l'exige.
+
+### 4.2 Mettre à jour
+
```bash
sudo apt update
+sudo apt full-upgrade -y
+sudo apt autoremove --purge -y
+sudo apt clean
```
-Lancement de l'installation :
+`full-upgrade` et non `upgrade` : le premier accepte d'installer ou de retirer des paquets quand une dépendance a changé, ce qui est exactement ce qu'on veut sur une machine neuve. `upgrade` bloquerait sur ces cas.
+
+### 4.3 Redémarrer si le noyau a changé
+
```bash
-sudo su -
-wget -O - https://get.ispconfig.org | sh -s --
+ls /var/run/reboot-required 2>/dev/null && echo "Redémarrage nécessaire"
+sudo reboot
```
+
+Après redémarrage, reconnectez-vous et vérifiez que tout est remonté :
+
+```bash
+systemctl is-system-running # attendu : running
+systemctl --failed # attendu : 0 loaded units listed
+uptime
+```
+
+Un état `degraded` signale au moins un service en échec ; `systemctl --failed` vous dit lequel.
+
+## Étape 5 — Paquets de base
+
+```bash
+sudo apt install -y \
+ vnstat iftop htop nano git \
+ curl wget ca-certificates gnupg \
+ dnsutils net-tools lsof tcpdump \
+ rsync tree zip unzip \
+ ncdu sysstat needrestart
+```
+
+| Paquet | À quoi il sert |
+| --- | --- |
+| `vnstat` | Compteur de trafic réseau historisé, léger (`vnstat -d`, `vnstat -m`) |
+| `iftop` | Trafic en temps réel par connexion |
+| `htop` | Processus, CPU, mémoire, en interactif |
+| `ncdu` | Trouve ce qui remplit le disque, en navigation |
+| `sysstat` | `sar`, `iostat`, `pidstat` : historique de charge et d'E/S |
+| `needrestart` | Signale après chaque `apt` les services à redémarrer |
+| `dnsutils` | `dig`, `nslookup` pour déboguer la résolution |
+| `lsof` / `tcpdump` | Qui tient un fichier, que passe-t-il sur le réseau |
+
+### Activer vnstat
+
+```bash
+sudo systemctl enable --now vnstat
+vnstat --iflist # vérifie l'interface détectée
+```
+
+Il faut attendre quelques heures avant que `vnstat -d` affiche des données utiles : le compteur démarre à zéro.
+
+### Ce que vous ne voulez probablement pas
+
+Sur un serveur, allez au plus maigre. Chaque paquet installé est une surface d'attaque et une mise à jour de plus. Évitez les méta-paquets `task-*`, les environnements de bureau, et tout serveur (`apache2`, `nginx`, `mariadb`) tant que vous n'êtes pas à l'étape de déploiement des services.
+
+```bash
+sudo apt-mark showmanual | head -50 # ce qui a été installé explicitement
+```
+
+## Étape 6 — Locale, fuseau horaire et clavier
+
+### 6.1 Locale
+
+Attention à l'orthographe : c'est `fr_FR.UTF-8` avec un **tiret**, pas `fr_FR.UTF_8`. Un underscore produit une locale invalide, silencieusement ignorée.
+
+Générez d'abord la locale, puis déclarez-la comme défaut système :
+
+```bash
+sudo sed -i 's/^# *\(fr_FR.UTF-8\)/\1/' /etc/locale.gen
+sudo locale-gen
+sudo localectl set-locale LANG=fr_FR.UTF-8
+```
+
+Variante non interactive, adaptée à un script :
+
+```bash
+echo "locales locales/locales_to_be_generated multiselect fr_FR.UTF-8 UTF-8, en_US.UTF-8 UTF-8" | sudo debconf-set-selections
+echo "locales locales/default_environment_locale select fr_FR.UTF-8" | sudo debconf-set-selections
+sudo rm -f /etc/locale.gen
+sudo dpkg-reconfigure --frontend=noninteractive locales
+```
+
+> `LANG=fr_FR.UTF-8` seul dans un terminal ne change que la session en cours. `localectl` écrit dans `/etc/default/locale`, lu par tous les services et toutes les futures connexions.
+
+**Recommandation** : gardez les **messages en anglais** même avec une interface en français. Les messages d'erreur anglais sont cherchables et correspondent à la documentation ; les scripts qui parsent une sortie de commande cassent en français.
+
+```bash
+sudo localectl set-locale LANG=fr_FR.UTF-8 LC_MESSAGES=C.UTF-8
+```
+
+Reconnectez-vous, puis vérifiez :
+
+```bash
+locale # aucune ligne "Cannot set LC_*"
+localectl status
+```
+
+### 6.2 Fuseau horaire
+
+```bash
+sudo timedatectl set-timezone Europe/Paris
+timedatectl list-timezones | grep Paris # pour trouver un autre fuseau
+```
+
+> Sur un parc international ou pour simplifier la lecture des journaux entre machines, `UTC` reste un choix défendable. Le seul vrai critère : que toutes vos machines aient **le même** fuseau.
+
+### 6.3 Synchronisation de l'heure
+
+Debian 13 utilise `systemd-timesyncd` par défaut. Une heure décalée casse TLS, les tokens et la corrélation des journaux.
+
+```bash
+sudo timedatectl set-ntp true
+timedatectl status
+```
+
+Attendu : `System clock synchronized: yes` et `NTP service: active`.
+
+Pour utiliser les serveurs français :
+
+```bash
+sudo mkdir -p /etc/systemd/timesyncd.conf.d
+printf '[Time]\nNTP=0.fr.pool.ntp.org 1.fr.pool.ntp.org\nFallbackNTP=2.fr.pool.ntp.org 3.fr.pool.ntp.org\n' \
+ | sudo tee /etc/systemd/timesyncd.conf.d/pool-fr.conf
+sudo systemctl restart systemd-timesyncd
+timedatectl timesync-status
+```
+
+### 6.4 Clavier (console uniquement)
+
+Utile seulement si vous passez par la console KVM de l'hébergeur ; sans effet sur SSH.
+
+```bash
+sudo localectl set-keymap fr
+sudo localectl set-x11-keymap fr
+```
+
+## Étape 7 — Compte administrateur et sudo
+
+### 7.1 Créer l'utilisateur
+
+```bash
+sudo adduser alix
+```
+
+Choisissez un mot de passe long et unique. Les champs « Nom complet », « N° de bureau », etc. peuvent rester vides : validez avec Entrée.
+
+### 7.2 Accorder les droits sudo
+
+Sous Debian, l'appartenance au groupe `sudo` suffit. Nul besoin d'éditer les sudoers pour un administrateur standard.
+
+```bash
+sudo usermod -aG sudo alix
+id alix # vérifie que "sudo" apparaît dans les groupes
+```
+
+> Le `-a` de `usermod -aG` est obligatoire : sans lui, l'utilisateur est **retiré de tous ses autres groupes**. C'est une erreur classique et difficile à diagnostiquer.
+
+Si vous avez besoin d'une règle spécifique — par exemple autoriser un redémarrage de service sans mot de passe — n'éditez **jamais** `/etc/sudoers` directement. Créez un fichier dédié dans `/etc/sudoers.d/`, ce qui isole la panne en cas d'erreur de syntaxe :
+
+```bash
+sudo visudo -f /etc/sudoers.d/10-alix
+```
+
+```
+# Redémarrage de nginx sans mot de passe
+alix ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx
+```
+
+```bash
+sudo chmod 0440 /etc/sudoers.d/10-alix
+sudo visudo -c # contrôle global de la syntaxe
+```
+
+> ⚠️ `visudo` valide la syntaxe avant d'écrire, ce que `nano /etc/sudoers` ne fait pas. Une erreur dans les sudoers non validée rend `sudo` inutilisable pour tout le monde, y compris vous.
+>
+> Évitez `NOPASSWD: ALL` : cela transforme toute exécution de code sous votre compte en accès root immédiat.
+
+### 7.3 Tester avant de couper quoi que ce soit
+
+Depuis **une nouvelle session** (en gardant l'ancienne ouverte) :
+
+```bash
+ssh alix@203.0.113.10
+sudo -v # doit demander VOTRE mot de passe et rendre la main
+sudo whoami # → root
+```
+
+Tant que ces trois commandes ne fonctionnent pas, n'allez pas plus loin : les étapes suivantes retirent votre accès actuel.
+
+### 7.4 Confort de connexion (optionnel)
+
+```bash
+# Depuis votre poste : alias de connexion
+cat >> ~/.ssh/config <<'EOF'
+Host web01
+ HostName web01.exemple.fr
+ User alix
+ Port 22
+ IdentityFile ~/.ssh/id_ed25519
+EOF
+```
+
+Vous vous connecterez ensuite avec `ssh web01`. Adaptez `Port` après l'étape 8 si vous le déplacez.
+
+## Étape 8 — Clés SSH et durcissement
+
+C'est l'étape la plus risquée. Gardez une session ouverte du début à la fin.
+
+### 8.1 Créer une paire de clés (sur votre poste, pas sur le serveur)
+
+```bash
+ssh-keygen -t ed25519 -C "alix@poste-bureau" -f ~/.ssh/id_ed25519
+```
+
+Ed25519 est le bon choix par défaut : court, rapide, sûr. Mettez une passphrase — elle protège la clé si votre poste est compromis, et `ssh-agent` évite de la retaper.
+
+### 8.2 Déposer la clé publique
+
+```bash
+ssh-copy-id -i ~/.ssh/id_ed25519.pub alix@203.0.113.10
+```
+
+En manuel si `ssh-copy-id` n'est pas disponible :
+
+```bash
+ssh alix@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
+cat ~/.ssh/id_ed25519.pub | ssh alix@203.0.113.10 "cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
+```
+
+Testez dans une **nouvelle** session : `ssh alix@203.0.113.10` doit passer sans demander le mot de passe du compte.
+
+### 8.3 Configurer sshd par fichier drop-in
+
+Debian 13 lit `/etc/ssh/sshd_config.d/*.conf`. Écrivez votre configuration là plutôt que dans `sshd_config` : vos choix survivent aux mises à jour du paquet et se retirent en supprimant un seul fichier.
+
+```bash
+sudo nano /etc/ssh/sshd_config.d/99-durcissement.conf
+```
+
+```
+# Authentification
+PermitRootLogin no
+PasswordAuthentication no
+KbdInteractiveAuthentication no
+PubkeyAuthentication yes
+AuthenticationMethods publickey
+MaxAuthTries 3
+MaxSessions 5
+LoginGraceTime 30
+
+# Limiter qui peut se connecter
+AllowUsers alix
+
+# Réduire la surface
+X11Forwarding no
+AllowAgentForwarding no
+AllowTcpForwarding no
+PermitTunnel no
+PermitUserEnvironment no
+
+# Sessions mortes
+ClientAliveInterval 300
+ClientAliveCountMax 2
+```
+
+> `AllowUsers alix` remplace avantageusement un `DenyUsers debian` : la liste blanche est explicite et couvre aussi les comptes que vous n'avez pas anticipés. Pensez à l'étendre si vous ajoutez un administrateur.
+
+> `PasswordAuthentication no` vous verrouille dehors si la clé de 8.2 ne fonctionne pas. Ne l'activez qu'après avoir vérifié la connexion par clé.
+
+Deux précautions : le premier fichier qui définit une directive gagne, et `sshd_config` charge souvent ses drop-ins **en première ligne**. Vérifiez donc la configuration réellement appliquée, jamais le fichier seul.
+
+```bash
+sudo sshd -t # syntaxe ; silence = OK
+sudo sshd -T | grep -Ei 'permitrootlogin|passwordauth|allowusers|^port'
+```
+
+Puis rechargez et testez depuis une nouvelle session :
+
+```bash
+sudo systemctl reload ssh
+```
+
+### 8.4 Changer le port : la spécificité Debian 13
+
+Depuis Debian 12, SSH est démarré par **activation à la demande via systemd** (`ssh.socket`). Conséquence : une directive `Port` dans `sshd_config` **peut rester sans effet**, car c'est le socket systemd qui décide de l'écoute.
+
+D'abord, constatez votre situation :
+
+```bash
+systemctl is-active ssh.socket # active → c'est le socket qui commande
+systemctl is-active ssh.service
+ss -tlpn | grep -E 'ssh|:22'
+```
+
+**Si `ssh.socket` est actif**, modifiez le socket :
+
+```bash
+sudo systemctl edit ssh.socket
+```
+
+```
+[Socket]
+ListenStream=
+ListenStream=0.0.0.0:2222
+ListenStream=[::]:2222
+```
+
+La ligne `ListenStream=` vide est indispensable : elle efface le port 22 hérité. Sans elle, vous ajoutez 2222 sans retirer 22.
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl restart ssh.socket
+ss -tlpn | grep 2222
+```
+
+**Alternative** — revenir au modèle classique, où `sshd_config` reprend la main :
+
+```bash
+sudo systemctl disable --now ssh.socket
+sudo systemctl enable --now ssh.service
+```
+
+### 8.5 Faut-il vraiment changer de port ?
+
+Ce n'est pas une mesure de sécurité, seulement de réduction du bruit : elle élimine les scans automatisés des journaux, pas un attaquant ciblé qui scannera vos 65 535 ports. Avec `PasswordAuthentication no` et fail2ban, le port 22 est déjà très défendable. Un port non standard complique en revanche le pare-feu, les sondes de supervision et les collaborateurs.
+
+### 8.6 Vérification finale
+
+Ouvrez une session neuve, sans fermer l'ancienne :
+
+```bash
+ssh -p 2222 alix@web01.exemple.fr
+ssh -p 2222 debian@web01.exemple.fr # doit être refusé
+ssh -p 2222 root@web01.exemple.fr # doit être refusé
+```
+
+## Étape 9 — Neutraliser le compte fournisseur
+
+Le compte `debian` livré par l'hébergeur est connu de tous et ciblé en premier par les scans. Une fois votre accès personnel prouvé, retirez-lui l'accès SSH.
+
+### 9.1 Choisir le niveau de neutralisation
+
+| Niveau | Commande | Effet | Quand |
+| --- | --- | --- | --- |
+| SSH bloqué | `AllowUsers alix` (étape 8.3) | Le compte existe, ne peut plus se connecter par SSH | Cas général |
+| Mot de passe verrouillé | `sudo passwd -l debian` | Plus d'authentification par mot de passe | À combiner avec le précédent |
+| Shell retiré | `sudo usermod -s /usr/sbin/nologin debian` | Plus aucune session interactive | Compte purement technique |
+| Compte supprimé | `sudo deluser --remove-home debian` | Disparu | Seulement si rien ne dépend de lui |
+
+La combinaison recommandée est la plus conservatrice :
+
+```bash
+sudo passwd -l debian
+sudo usermod -s /usr/sbin/nologin debian
+sudo rm -f /home/debian/.ssh/authorized_keys
+```
+
+> ⚠️ Ne supprimez pas le compte avant d'avoir vérifié qu'aucun processus ne tourne sous son identité (`ps -u debian`) et qu'il n'est pas utilisé par l'outillage de l'hébergeur (agent de sauvegarde, `cloud-init`, console de secours). Certains hébergeurs recréent le compte à chaque redémarrage.
+
+### 9.2 Le cas de root
+
+```bash
+sudo passwd -l root # verrouille le mot de passe root
+sudo rm -f /root/.ssh/authorized_keys
+```
+
+Sur Debian, root n'a généralement pas de mot de passe utilisable en SSH dès lors que `PermitRootLogin no` est posé. Le verrouillage est une ceinture en plus des bretelles.
+
+> N'utilisez pas `usermod -s /usr/sbin/nologin root` : vous perdriez l'accès par la console de secours de l'hébergeur, votre dernier recours.
+
+### 9.3 Inventaire des comptes
+
+```bash
+# Comptes capables de se connecter
+awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $7}' /etc/passwd
+
+# Membres du groupe sudo
+getent group sudo
+
+# Comptes sans mot de passe (doit être vide)
+sudo awk -F: '$2 == "" {print $1}' /etc/shadow
+
+# Clés SSH autorisées sur toute la machine
+sudo find /home /root -name authorized_keys -exec ls -l {} \; -exec cat {} \;
+```
+
+La dernière commande mérite un passage attentif : une clé publique inconnue dans un `authorized_keys` est une porte dérobée.
+
+## Étape 10 — Pare-feu
+
+Debian 13 utilise **nftables** comme moteur de filtrage. Deux approches : `nftables` directement, ou `ufw` qui l'utilise en coulisse avec une syntaxe plus simple.
+
+### 10.1 Option A — ufw (recommandé si vous débutez)
+
+```bash
+sudo apt install -y ufw
+
+# Politique par défaut : tout entrant bloqué, tout sortant autorisé
+sudo ufw default deny incoming
+sudo ufw default allow outgoing
+
+# SSH EN PREMIER — sinon vous vous coupez l'accès à l'activation
+sudo ufw limit 2222/tcp comment 'SSH'
+
+# Services web, à n'ouvrir que le jour où vous les déployez
+# sudo ufw allow 80/tcp comment 'HTTP'
+# sudo ufw allow 443/tcp comment 'HTTPS'
+
+sudo ufw enable
+sudo ufw status verbose
+```
+
+`limit` plutôt que `allow` pour SSH : ufw bloque une IP qui dépasse six tentatives de connexion en 30 secondes. C'est une première barrière avant fail2ban.
+
+### 10.2 Option B — nftables directement
+
+Plus verbeux, mais sans couche intermédiaire et lisible d'un seul coup d'œil.
+
+```bash
+sudo nano /etc/nftables.conf
+```
+
+```
+#!/usr/sbin/nft -f
+flush ruleset
+
+table inet filter {
+ chain input {
+ type filter hook input priority filter; policy drop;
+
+ ct state established,related accept
+ ct state invalid drop
+ iif lo accept
+
+ ip protocol icmp accept
+ ip6 nexthdr icmpv6 accept
+
+ tcp dport 2222 ct state new limit rate 6/minute accept
+ # tcp dport { 80, 443 } accept
+
+ counter
+ }
+
+ chain forward {
+ type filter hook forward priority filter; policy drop;
+ }
+
+ chain output {
+ type filter hook output priority filter; policy accept;
+ }
+}
+```
+
+```bash
+sudo nft -c -f /etc/nftables.conf # vérifie la syntaxe sans appliquer
+sudo systemctl enable --now nftables
+sudo nft list ruleset
+```
+
+> ⚠️ Ne laissez jamais `policy drop` sur `input` sans règle SSH au-dessus. Testez toujours avec `nft -c -f` avant d'appliquer.
+
+### 10.3 Filet de sécurité pendant les tests
+
+Programmez une désactivation automatique du pare-feu dans 10 minutes. Si vous vous verrouillez dehors, l'accès revient seul ; si tout va bien, vous annulez la tâche.
+
+```bash
+# Avant d'activer les règles
+sudo systemd-run --on-active=10min --unit=ufw-panic systemctl stop ufw
+
+# Une fois la connexion reconfirmée depuis une nouvelle session
+sudo systemctl stop ufw-panic.timer
+```
+
+### 10.4 Le pare-feu de l'hébergeur
+
+Beaucoup d'hébergeurs interposent leur propre filtrage en amont (*security group*, « firewall network »). Un port ouvert sur la machine et fermé chez eux reste inaccessible — et l'inverse est vrai. Tenez les deux couches alignées, et documentez-les ensemble.
+
+```bash
+# Depuis un autre poste : ce qui est réellement joignable
+nmap -Pn -p- web01.exemple.fr
+```
+
+## Étape 11 — fail2ban
+
+fail2ban lit les journaux et bannit temporairement les IP qui échouent trop souvent. Avec `PasswordAuthentication no`, son utilité sur SSH est surtout de nettoyer les journaux ; elle redevient essentielle dès que vous exposez un service authentifié par mot de passe.
+
+```bash
+sudo apt install -y fail2ban
+```
+
+### Configuration
+
+Ne modifiez jamais `jail.conf` : il est écrasé aux mises à jour. Créez `jail.local`.
+
+```bash
+sudo nano /etc/fail2ban/jail.local
+```
+
+```ini
+[DEFAULT]
+bantime = 1h
+findtime = 10m
+maxretry = 4
+backend = systemd
+banaction = nftables-multiport
+# Ne bannissez jamais votre propre IP fixe
+ignoreip = 127.0.0.1/8 ::1 198.51.100.7
+
+[sshd]
+enabled = true
+port = 2222
+mode = aggressive
+```
+
+`backend = systemd` est important sous Debian 13 : les journaux passent par `journald`, pas par un fichier `/var/log/auth.log` garanti. `banaction = nftables-multiport` évite un conflit avec le moteur nftables du système.
+
+> Si vous avez choisi ufw à l'étape 10, utilisez plutôt `banaction = ufw`.
+
+```bash
+sudo systemctl enable --now fail2ban
+sudo systemctl restart fail2ban
+```
+
+### Exploitation au quotidien
+
+```bash
+sudo fail2ban-client status # prisons actives
+sudo fail2ban-client status sshd # IP bannies
+sudo fail2ban-client set sshd unbanip 198.51.100.7 # débannir
+sudo fail2ban-client set sshd banip 203.0.113.99 # bannir à la main
+```
+
+> ⚠️ Mettez votre IP fixe dans `ignoreip` **avant** de démarrer le service. Sinon, une passphrase mal tapée quatre fois vous bannit une heure de votre propre serveur.
+
+## Étape 12 — Mises à jour de sécurité automatiques
+
+Un serveur non mis à jour devient vulnérable en quelques semaines. `unattended-upgrades` applique les correctifs de sécurité sans intervention.
+
+```bash
+sudo apt install -y unattended-upgrades apt-listchanges
+sudo dpkg-reconfigure -plow unattended-upgrades
+```
+
+### Configuration
+
+```bash
+sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
+```
+
+Lignes à vérifier ou décommenter :
+
+```
+Unattended-Upgrade::Origins-Pattern {
+ "origin=Debian,codename=${distro_codename},label=Debian-Security";
+ "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
+};
+
+Unattended-Upgrade::Mail "alix@exemple.fr";
+Unattended-Upgrade::MailReport "on-change";
+Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
+Unattended-Upgrade::Remove-Unused-Dependencies "true";
+Unattended-Upgrade::Automatic-Reboot "false";
+Unattended-Upgrade::Automatic-Reboot-Time "04:00";
+```
+
+Le choix structurant est `Automatic-Reboot` :
+
+| Valeur | Conséquence |
+| --- | --- |
+| `"false"` | Les correctifs noyau attendent un redémarrage manuel. Le serveur reste vulnérable en attendant, mais ne tombe jamais seul. |
+| `"true"` | Redémarrage automatique à 04:00 si nécessaire. Correctifs réellement actifs, au prix d'une coupure imprévisible. |
+
+Pour un serveur de production isolé, `"true"` avec une heure creuse est souvent le meilleur compromis. Pour un serveur critique sans redondance, gardez `"false"` et redémarrez lors d'une fenêtre planifiée.
+
+### Vérifier que ça tourne
+
+```bash
+sudo unattended-upgrade --dry-run --debug # simulation détaillée
+systemctl list-timers | grep -E 'apt|unattended'
+cat /var/log/unattended-upgrades/unattended-upgrades.log
+```
+
+Deux minuteries doivent apparaître : `apt-daily.timer` (rafraîchissement des index) et `apt-daily-upgrade.timer` (installation).
+
+### Savoir quand redémarrer
+
+```bash
+cat /var/run/reboot-required.pkgs 2>/dev/null # paquets concernés
+sudo needrestart -b # services à relancer
+```
+
+Pensez à intégrer cette vérification à votre routine hebdomadaire.
+
+## Étape 13 — Swap, /tmp et paramètres noyau
+
+### 13.1 Swap
+
+Beaucoup de VPS sont livrés sans swap. Un peu de swap évite qu'un pic de mémoire déclenche le tueur de processus du noyau (OOM killer).
+
+```bash
+free -h # vérifier ce qui existe déjà
+swapon --show
+```
+
+Si la ligne Swap est à zéro :
+
+```bash
+sudo fallocate -l 2G /swapfile
+sudo chmod 600 /swapfile
+sudo mkswap /swapfile
+sudo swapon /swapfile
+echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
+```
+
+Dimensionnement raisonnable : 2 Go jusqu'à 4 Go de RAM, puis 4 Go au-delà. Inutile d'aller au-delà sur un serveur : si vous swappez beaucoup, il faut de la RAM, pas du disque.
+
+```bash
+# Réduire l'agressivité du swap sur un serveur
+echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
+```
+
+> Sur SSD NVMe, le swap est peu coûteux. Sur un disque réseau facturé aux IOPS, il peut coûter cher et ralentir fortement.
+
+### 13.2 /tmp est désormais en RAM
+
+Changement notable de Debian 13 : `/tmp` est monté en **tmpfs**, donc en mémoire, et vidé à chaque redémarrage ([note de version](https://www.debian.org/releases/trixie/release-notes/issues.en.html)).
+
+```bash
+df -h /tmp
+findmnt /tmp
+```
+
+Deux conséquences à connaître :
+
+1. Écrire un gros fichier dans `/tmp` consomme de la RAM. Les traitements volumineux doivent utiliser `/var/tmp`, qui reste sur disque.
+2. Sur une machine migrée depuis Debian 12, les anciens fichiers de `/tmp` sont toujours sur le disque, masqués par le montage. Ils occupent de l'espace invisible.
+
+```bash
+# Retrouver et nettoyer l'ancien /tmp masqué
+sudo mkdir -p /mnt/racine
+sudo mount --bind / /mnt/racine
+ls -lha /mnt/racine/tmp/
+# ... supprimez ce qui doit l'être ...
+sudo umount /mnt/racine && sudo rmdir /mnt/racine
+```
+
+Pour repasser `/tmp` sur disque si votre usage le demande :
+
+```bash
+sudo systemctl mask tmp.mount
+sudo reboot
+```
+
+### 13.3 Paramètres réseau et noyau
+
+```bash
+sudo nano /etc/sysctl.d/99-durcissement.conf
+```
+
+```
+# Anti-usurpation d'adresse
+net.ipv4.conf.all.rp_filter = 1
+net.ipv4.conf.default.rp_filter = 1
+
+# Ignorer le routage par la source et les redirections ICMP
+net.ipv4.conf.all.accept_source_route = 0
+net.ipv6.conf.all.accept_source_route = 0
+net.ipv4.conf.all.accept_redirects = 0
+net.ipv6.conf.all.accept_redirects = 0
+net.ipv4.conf.all.send_redirects = 0
+
+# Journaliser les paquets manifestement usurpés
+net.ipv4.conf.all.log_martians = 1
+
+# Résistance aux SYN flood
+net.ipv4.tcp_syncookies = 1
+
+# Limiter la lecture des informations noyau
+kernel.dmesg_restrict = 1
+kernel.kptr_restrict = 2
+
+# Protection des liens en répertoires partagés
+fs.protected_hardlinks = 1
+fs.protected_symlinks = 1
+```
+
+```bash
+sudo sysctl --system
+sudo sysctl -a --pattern 'tcp_syncookies|rp_filter' # contrôle
+```
+
+> N'appliquez pas `net.ipv4.ip_forward = 0` sans réfléchir : Docker, les conteneurs et les VPN en ont besoin.
+
+## Étape 14 — Journaux, supervision et alertes
+
+### 14.1 Plafonner les journaux
+
+Par défaut, `journald` peut occuper jusqu'à 10 % du système de fichiers. Sur un petit VPS, c'est une cause classique de disque plein.
+
+```bash
+sudo nano /etc/systemd/journald.conf.d/00-limites.conf
+```
+
+```
+[Journal]
+Storage=persistent
+SystemMaxUse=500M
+SystemMaxFileSize=50M
+MaxRetentionSec=1month
+```
+
+```bash
+sudo mkdir -p /etc/systemd/journald.conf.d
+sudo systemctl restart systemd-journald
+journalctl --disk-usage
+```
+
+### 14.2 Commandes de lecture utiles
+
+```bash
+journalctl -p err -b # erreurs depuis le démarrage
+journalctl -u ssh --since "1 hour ago" # un service, une fenêtre de temps
+journalctl -f # en direct
+journalctl --since yesterday | grep -i "failed password"
+last -20 # dernières connexions réussies
+lastb -20 # dernières tentatives échouées
+```
+
+### 14.3 Recevoir les alertes par mail
+
+Sans MTA, les rapports de `unattended-upgrades`, `cron` et `fail2ban` sont écrits mais jamais lus. Un relais léger suffit — n'installez pas un serveur de mail complet.
+
+```bash
+sudo apt install -y msmtp-mta bsd-mailx
+sudo nano /etc/msmtprc
+```
+
+```
+defaults
+auth on
+tls on
+tls_trust_file /etc/ssl/certs/ca-certificates.crt
+logfile /var/log/msmtp.log
+
+account default
+host smtp.exemple.fr
+port 587
+from web01@exemple.fr
+user web01@exemple.fr
+password VOTRE_MOT_DE_PASSE
+```
+
+```bash
+sudo chmod 600 /etc/msmtprc
+echo "Test depuis web01" | mail -s "Test alerte" alix@exemple.fr
+```
+
+> Le fichier contient un mot de passe en clair : `chmod 600` est obligatoire. Préférez un mot de passe d'application dédié, révocable, plutôt que votre mot de passe principal.
+
+Redirigez ensuite le courrier de root vers vous :
+
+```bash
+echo "root: alix@exemple.fr" | sudo tee -a /etc/aliases
+sudo newaliases 2>/dev/null || true
+```
+
+### 14.4 Surveiller l'essentiel
+
+```bash
+# Trafic réseau
+vnstat -d # par jour
+vnstat -m # par mois, utile face à un quota
+
+# Disque
+df -h
+sudo ncdu / # exploration interactive
+
+# Charge et E/S
+uptime
+iostat -x 2 5
+sar -u 1 5
+```
+
+Une alerte simple sur le disque, via cron, vaut mieux qu'une supervision compliquée jamais installée :
+
+```bash
+sudo tee /etc/cron.daily/alerte-disque >/dev/null <<'EOF'
+#!/bin/sh
+SEUIL=85
+USAGE=$(df / --output=pcent | tail -1 | tr -dc '0-9')
+[ "$USAGE" -ge "$SEUIL" ] && echo "Disque / à ${USAGE}% sur $(hostname -f)" \
+ | mail -s "ALERTE disque $(hostname)" root
+exit 0
+EOF
+sudo chmod +x /etc/cron.daily/alerte-disque
+```
+
+## Étape 15 — Sauvegarde et instantané de référence
+
+### 15.1 Instantané immédiat
+
+Vous venez de construire une base propre. Prenez-en un instantané (*snapshot*) chez votre hébergeur **maintenant**, avant de déployer le moindre service. C'est votre point de retour : une mauvaise manipulation plus tard se résoudra en trois minutes au lieu d'une réinstallation complète.
+
+### 15.2 Archiver la configuration
+
+```bash
+sudo tar czf /root/config-initiale-$(date +%F).tar.gz \
+ /etc/ssh/sshd_config.d /etc/hosts /etc/hostname \
+ /etc/apt/sources.list.d /etc/sudoers.d \
+ /etc/fail2ban/jail.local /etc/nftables.conf \
+ /etc/sysctl.d /etc/default/locale 2>/dev/null
+```
+
+Récupérez l'archive sur votre poste :
+
+```bash
+scp -P 2222 alix@web01.exemple.fr:/root/config-initiale-*.tar.gz ./
+```
+
+> Mieux encore : versionnez ces fichiers dans un dépôt Git privé — sans les secrets. `git` est déjà installé à l'étape 5.
+
+### 15.3 Mettre en place une vraie sauvegarde
+
+Une sauvegarde qu'on n'a jamais restaurée n'est pas une sauvegarde. Principe des 3-2-1 : trois copies, deux supports, une hors site.
+
+```bash
+sudo apt install -y restic
+```
+
+```bash
+# Initialisation vers un stockage distant (une seule fois)
+export RESTIC_REPOSITORY="sftp:sauvegarde@stockage.exemple.fr:/backups/web01"
+export RESTIC_PASSWORD_FILE="/root/.restic-pass"
+sudo restic init
+
+# Sauvegarde
+sudo restic backup /etc /home /var/www --exclude-caches
+
+# Vérification et purge
+sudo restic snapshots
+sudo restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
+```
+
+Automatisez avec une minuterie systemd plutôt qu'un cron : les échecs remontent dans `journalctl`.
+
+```bash
+sudo systemd-run --on-calendar="*-*-* 03:00:00" --unit=sauvegarde \
+ /usr/bin/restic backup /etc /home /var/www
+```
+
+### 15.4 Tester la restauration
+
+À faire une fois, tout de suite, puis tous les trimestres :
+
+```bash
+sudo restic restore latest --target /tmp/test-restauration --include /etc/hosts
+cat /tmp/test-restauration/etc/hosts
+```
+
+Notez la date du dernier test réussi quelque part de visible. C'est la seule métrique qui compte vraiment.
+
+## Checklist récapitulative
+
+### Préparatifs
+
+- [ ] Accès de secours hors SSH vérifié (console KVM, mode rescue)
+- [ ] Enregistrement A (et AAAA) créé vers le FQDN
+- [ ] Reverse DNS (PTR) aligné sur le FQDN, IPv4 et IPv6
+- [ ] `dig` confirme la correspondance dans les deux sens
+
+### Identité et système
+
+- [ ] Première connexion réussie, état initial relevé (`ss -tulpn`)
+- [ ] Nom d'hôte court défini avec `hostnamectl set-hostname`
+- [ ] `/etc/hosts` corrigé : FQDN avant nom court sur la ligne `127.0.1.1`
+- [ ] `hostname -f` renvoie bien le FQDN
+- [ ] Sources APT converties en deb822, `trixie-security` présent
+- [ ] `apt full-upgrade` passé, machine redémarrée si le noyau a changé
+- [ ] `systemctl --failed` ne renvoie rien
+- [ ] Paquets de base installés, `vnstat` activé
+- [ ] Locale `fr_FR.UTF-8` générée et définie (avec un tiret)
+- [ ] Fuseau horaire posé, `timedatectl` indique l'horloge synchronisée
+
+### Accès
+
+- [ ] Compte administrateur créé et ajouté au groupe `sudo` (avec `-aG`)
+- [ ] `sudo -v` et `sudo whoami` fonctionnent depuis le nouveau compte
+- [ ] Clé Ed25519 générée et déposée, connexion par clé vérifiée
+- [ ] Drop-in `sshd_config.d` créé : root refusé, mot de passe désactivé, `AllowUsers` posé
+- [ ] `sudo sshd -T` confirme la configuration réellement appliquée
+- [ ] Port SSH vérifié côté `ssh.socket` si vous l'avez changé
+- [ ] Compte fournisseur verrouillé, ses clés SSH retirées
+- [ ] Aucune clé inconnue dans les `authorized_keys` de la machine
+
+### Protection
+
+- [ ] Pare-feu actif, SSH autorisé **avant** activation
+- [ ] Ports ouverts alignés entre la machine et le pare-feu de l'hébergeur
+- [ ] fail2ban actif, votre IP fixe dans `ignoreip`
+- [ ] `unattended-upgrades` actif, politique de redémarrage décidée
+- [ ] Paramètres sysctl appliqués (`sysctl --system`)
+- [ ] Swap présent si la RAM est limitée
+
+### Exploitation
+
+- [ ] Journaux plafonnés (`journalctl --disk-usage`)
+- [ ] Envoi de mail testé, courrier de root redirigé
+- [ ] Sauvegarde configurée **et restauration testée une fois**
+- [ ] Instantané de référence pris chez l'hébergeur
+- [ ] Archive de configuration récupérée hors du serveur
+- [ ] TTL DNS remonté à sa valeur normale
+
+### Vérification finale d'un seul bloc
+
+```bash
+hostname -f; echo '---'
+localectl status | head -3; echo '---'
+timedatectl | grep -E 'Time zone|synchronized'; echo '---'
+sudo sshd -T | grep -E '^(port|permitrootlogin|passwordauthentication|allowusers)'; echo '---'
+sudo ufw status verbose 2>/dev/null || sudo nft list ruleset | head -20; echo '---'
+sudo fail2ban-client status; echo '---'
+systemctl --failed; echo '---'
+free -h; df -h /
+```
+
+## Ce qui change par rapport à l'ancienne fiche Debian 11
+
+L'ancienne fiche couvrait l'essentiel de la mise en route. Voici ce qui y était inexact ou
+incomplet, et pourquoi c'est corrigé ici.
+
+| Ancienne fiche | Correction | Pourquoi |
+| --- | --- | --- |
+| `LANG=fr_FR.UTF_8` | `fr_FR.UTF-8` | Tiret et non underscore ; sinon la locale est invalide. Et `LANG=` seul ne dure que le temps de la session : utilisez `localectl set-locale` |
+| Ordre dans `/etc/hosts` « avant les noms déjà renseignés » | FQDN puis nom court, dans cet ordre | `hostname -f` prend le **premier** nom de la ligne. Inversé, il renvoie le nom court |
+| `adduser nom` | `sudo adduser nom` | La création d'utilisateur demande les privilèges root |
+| Droits supplémentaires via `visudo` | `usermod -aG sudo` d'abord ; `visudo -f /etc/sudoers.d/10-nom` si besoin spécifique | L'appartenance au groupe suffit dans 95 % des cas. Un fichier dédié isole une erreur de syntaxe au lieu de casser `sudo` pour tout le monde |
+| `apt upgrade -y` | `apt full-upgrade -y` | `upgrade` refuse d'installer ou de retirer des paquets, donc bloque sur des transitions courantes d'une machine neuve |
+| « Désactiver ssh pour l'utilisateur `debian` » | `AllowUsers` en liste blanche + verrouillage du compte | Une liste blanche couvre aussi les comptes non anticipés ; le verrouillage ferme les autres voies que SSH |
+
+### Ce que l'ancienne fiche ne couvrait pas
+
+1. **Les clés SSH avant la désactivation du mot de passe.** C'est la seule séquence qui ne pardonne pas l'inversion.
+2. **Le pare-feu.** Sans lui, chaque service déployé est exposé par défaut.
+3. **Les mises à jour automatiques.** Un serveur à jour le jour de l'installation ne l'est plus trois semaines après.
+4. **La sauvegarde.** Y compris le test de restauration, qui est la partie qu'on saute toujours.
+
+### Pièges spécifiques à Debian 13
+
+| Piège | Symptôme | Solution |
+| --- | --- | --- |
+| SSH en activation par socket | `Port 2222` dans `sshd_config` ignoré, SSH reste sur 22 | `systemctl edit ssh.socket` avec un `ListenStream=` vide puis le nouveau port (étape 8.4) |
+| `/tmp` en tmpfs | Espace disque « disparu » après migration ; gros fichiers qui saturent la RAM | Nettoyer l'ancien `/tmp` masqué, utiliser `/var/tmp` pour le volumineux (étape 13.2) |
+| Sources au format deb822 | Un script qui écrit dans `/etc/apt/sources.list` semble sans effet | Écrire dans `/etc/apt/sources.list.d/*.sources` |
+| `cloud-init` | Le nom d'hôte revient à sa valeur d'origine après redémarrage | `preserve_hostname: true` (étape 3.3) |
+
+## Sources
+
+- [Format deb822 sous Trixie — dev.to](https://dev.to/r3m8/debian-13-trixie-adoptez-le-nouveau-format-deb822-1ml6)
+- [Migration vers deb822 — OSTechNix](https://ostechnix.com/migrate-to-deb822-format-debian-13-trixie/)
+- [Changer le port SSH sous Debian 13 — IONOS](https://www.ionos.com/help/server-cloud-infrastructure/getting-started/important-security-information-for-your-server/changing-the-ssh-port/)
+- [Notes de publication de Debian 13 — problèmes connus](https://www.debian.org/releases/trixie/release-notes/issues.en.html)
diff --git a/docs/technique/serveur-debian.md b/docs/technique/serveur-debian.md
new file mode 100644
index 0000000..69d1480
--- /dev/null
+++ b/docs/technique/serveur-debian.md
@@ -0,0 +1,11 @@
+---
+description: Cette fiche a été remplacée par la procédure de préparation d'un serveur Debian 13 (Trixie).
+---
+
+# Préparation serveur Debian — page déplacée
+
+Cette fiche visait Debian 11. Elle est remplacée par une procédure complète et à jour :
+
+[:octicons-arrow-right-24: Préparation d'un serveur Debian 13 (Trixie)](serveur-debian-13.md)
+
+Cette page ne subsiste que pour ne pas casser les liens partagés vers l'ancienne adresse.
diff --git a/mkdocs.yml b/mkdocs.yml
index 27d6bc9..d423571 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -35,7 +35,13 @@ extra_css:
markdown_extensions:
- admonition
- pymdownx.details
- - pymdownx.superfences
+ - pymdownx.superfences:
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_div_format
+ - pymdownx.tasklist:
+ custom_checkbox: true
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
@@ -97,7 +103,7 @@ nav:
- technique/nextcloud.md
- technique/matrix.md
- technique/arduino-ide.md
- - technique/serveur-debian.md
+ - technique/serveur-debian-13.md
- technique/bigbluebutton.md
- technique/ateliers.md
- Communication: communication/index.md