Formation pratique sécurité Linux et DevSecOps, pilotée par la CLI
dsoxlab. Ce dépôt est le catalogue
de labs de la formation Linux du site
www.stephane-robert.info,
orienté vers les certifications RHCSA (EX200 v10) et LFCS, avec un angle
de durcissement systématique.
linux-dsoxlab-training est un dépôt de contenu, pas une application. Il
propose :
- des labs guidés avec des instructions précises,
- des challenges sans pas-à-pas, pour vérifier l'autonomie,
- des capstones qui synthétisent un bloc entier,
- une validation automatique qui prouve l'état du système (et non qu'une commande a été tapée),
- un scoring avec des indices à coût variable.
La CLI dsoxlab est le seul point d'entrée : elle démarre un lab, affiche les
instructions, valide, note et fait le bilan. Elle vit dans son propre dépôt
et s'installe séparément : elle ne fait pas partie de ce dépôt.
- Python 3.11+ et
uv git- Pour les labs L2+ (VM : systemd, pare-feu, SELinux, stockage), un provider parmi KVM/libvirt, Incus ou un cloud supporté (Outscale). Les labs shell (L1) ne demandent qu'un terminal.
dsoxlab est publié sur PyPI : on
l'installe comme un outil autonome.
# 1. Installer la CLI dsoxlab (outil externe, hors de ce dépôt)
uv tool install dsoxlab # ou : pipx install dsoxlab
# 2. Cloner ce catalogue de labs
git clone https://github.com/stephrobert/linux-dsoxlab-training.git
cd linux-dsoxlab-training
# 3. Vérifier que tout est en place
dsoxlab doctorCommence par la section l1. Ses vingt labs tournent dans un simple
terminal : aucune machine virtuelle, aucun provider, rien à provisionner. Tu
peux les faire sur ton poste, tout de suite.
dsoxlab use l1 # section de départ
dsoxlab next # → l1-first-terminalPuis, pour ce lab comme pour tous les autres, le même cycle en quatre temps :
dsoxlab course l1-first-terminal # 1. le contexte, puis le cours
dsoxlab challenge l1-first-terminal # 2. ce qui t'est demandé
dsoxlab run l1-first-terminal # 3. prépare ton espace de travail
# (challenge/work/) et t'y place
dsoxlab check l1-first-terminal # 4. valide et noterun est l'étape que l'on oublie : c'est elle qui crée les fichiers sur
lesquels tu travailles, et pour un lab VM, qui met la machine dans l'état
décrit par le scénario. Un check lancé sans run échoue en annonçant que
rien n'est fait, ce qui est vrai mais trompeur.
Bloqué ? dsoxlab hint <id> révèle un indice, au prix de quelques points.
Les sections l2 et suivantes configurent de vrais systèmes : systemd,
pare-feu, SELinux, stockage. Elles demandent un provider actif et une
infrastructure provisionnée.
dsoxlab use --provider kvm # persisté pour ce dépôt
dsoxlab provision # crée les machines (quelques minutes)
dsoxlab status # vérifie qu'elles répondentSi une machine devient inaccessible, voir Récupérer une machine devenue inaccessible.
Vérifie ton environnement avec dsoxlab doctor (Python, pytest, runtimes, labs
détectés). Ce dépôt déclare plusieurs providers d'infrastructure : les labs VM
en exigent donc un actif.
De nouveaux labs arrivent dans ce dépôt, et la CLI évolue de son côté. Mets à jour chacun séparément :
git pull # récupère les labs nouveaux/mis à jour dans ton clone
uv tool upgrade dsoxlab # met à jour la CLI (ou : pipx upgrade dsoxlab)Tes réponses en cours vivent dans le challenge/work/ de chaque lab, qui est
gitignoré ; git pull apporte donc les nouveaux labs sans jamais toucher à ton
travail.
Le catalogue est décrit par des données, pas par du code : le moteur dsoxlab
reste agnostique du domaine et lit deux niveaux de fichiers.
meta.ymlà la racine déclare l'identité du dépôt, la topologie d'infrastructure (réseau, hôtes, providers) et l'ordre des sections affiché parlist-labs.lab.yamlpar lab (souslabs/linux/<section>/<lab>/) déclare sesskills, sonlevel, sonruntime(shell/incus/kvm et hôte cible), sesdistros, sondoc_urlet un blocvalidation(functional,security,persistence_after_reboot). Unlab.fr.yamloptionnel surcharge letitleet ladescriptionen français.
dsoxlab validate-structure vérifie tout le contrat : le meta.yml est
conforme, chaque lab référencé existe avec un lab.yaml valide, chaque
runtime.host pointe un hôte déclaré, et chaque fichier de test ou script
référencé est présent.
L'apprenant pilote tout via la CLI ; un parcours type :
dsoxlab use --provider kvm # choisir un provider d'infra (labs VM)
dsoxlab doctor # vérifier l'environnement (Python, pytest, runtimes, labs)
dsoxlab list-labs # parcourir le catalogue
dsoxlab show <id> # métadonnées et statut d'un lab
dsoxlab run <id> # préparer et démarrer l'environnement
dsoxlab course <id> # lire le cours guidé (optionnel)
dsoxlab challenge <id> # lire la mission (sans pas-à-pas)
dsoxlab hint <id> # révéler un indice (déduit du score)
dsoxlab check <id> # lancer les tests, calculer et noter
dsoxlab submit <id> # soumission finale, ferme la session
dsoxlab progress # progression par bloc, score moyenC'est run qui monte l'environnement. Pour un lab shell, il crée le
workdir du lab et copie les fixtures déclarées. Pour un lab VM, il
sélectionne l'hôte cible (provisionné par Terraform) et applique la mise en
place du lab avec Ansible.
| Runtime | Backend | Ce qu'il apporte |
|---|---|---|
shell |
shell local | Exercices mono-hôte rapides (fichiers, texte, permissions). Sans coût de VM : les tests tournent sur ta propre machine et valident son état réel. |
incus |
conteneurs Incus | Environnements Linux isolés, à démarrage rapide. |
kvm |
Terraform + libvirt | VM complètes, le seul runtime capable de prouver le reboot/la persistance (systemd, pare-feu, SELinux, stockage). |
Les labs VM sont provisionnés une fois avec dsoxlab provision (Terraform) et
détruits avec dsoxlab destroy. Les providers (KVM/Incus/Outscale) sont
interchangeables et choisis par dépôt via dsoxlab use --provider <nom> ; les
IP sont attribuées par le provider, jamais codées en dur.
La validation prouve l'état du système, elle ne fait pas confiance à
l'apprenant. Chaque lab embarque des tests pytest/pytest-testinfra sous
challenge/tests/ qui vérifient des faits sur la machine : le service tourne
et est activé, le montage est présent et déclaré dans /etc/fstab par
UUID, le contexte SELinux est posé de façon persistante. Un test qui vérifie
seulement qu'une commande a été tapée est rejeté.
- En CI / mode formateur, une fixture du
conftest.pyracine rejoue la solution de référence (solution/) avant les tests, pour prouver que la solution elle-même est correcte. - Dans
dsoxlab check(le parcours apprenant), ce rejeu est désactivé (LAB_NO_REPLAY=1) : les tests valident le travail de l'apprenant. - La persistance après reboot est un critère de premier ordre : c'est précisément ce qui fait échouer les candidats RHCSA, donc un lab VM qui configure quelque chose censé survivre à un reboot le vérifie explicitement.
check enregistre un score (tests réussis/total, moins le coût des indices
utilisés). Les indices sont à coût variable : en révéler un déduit des
points, d'où leur caractère opt-in. L'historique vit dans une base SQLite propre à ce dépôt
(.dsoxlab.db, à la racine, gitignorée) ; dsoxlab scores et
dsoxlab progress la lisent. La session active (contexte, provider) est
stockée par dépôt dans .dsoxlab-context.json.
Un lab qui casse volontairement SSH, le réseau ou le montage racine peut laisser une VM injoignable, et c'est parfois le but de l'exercice. Quand la machine ne répond plus et que la console ne suffit pas, la voie fiable est de reconstruire le parc :
dsoxlab destroy --yes # environ 6 s
dsoxlab provision # environ 4 min, les 3 hôtes reviennent prêtsLes IP sont réattribuées à l'identique (10.10.30.11 à .13) : le fragment
ssh_config et l'inventaire sont régénérés, rien d'autre n'est à retoucher. La
progression n'est pas touchée : elle vit dans .dsoxlab.db, pas dans les VM.
dsoxlab destroy --host <fqdn> existe, mais ne récupère pas une seule
machine : Terraform détruit aussi tout ce qui dépend de la cible, si bien que
demander un hôte en emporte d'autres (mesuré : 7 ressources planifiées pour une
seule demandée). Ne s'en servir que pour restreindre un plan, jamais comme
procédure de récupération.
Les labs vivent sous labs/linux/ et sont ordonnés par meta.yml. La table
ci-dessous est générée à partir des vrais lab.yaml : lance
python3 scripts/gen_catalog.py pour la rafraîchir.
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
l1-first-terminal |
Premiers pas dans le terminal | l1 | RHCSA · LFCS | shell | guide |
l1-discover-linux-map |
Cartographier Linux : noyau, distribution et répertoires clés | l1 | RHCSA · LFCS | shell | guide |
l1-choose-distro |
Choisir sa distribution Linux de référence | l1 | RHCSA · LFCS | shell | guide |
l1-prepare-vm |
Identifier sa machine Linux | l1 | RHCSA · LFCS | shell | guide |
l1-read-a-command |
Lire et décoder une commande | l1 | RHCSA · LFCS | shell | guide |
l1-get-help |
Obtenir de l'aide en ligne de commande | l1 | RHCSA · LFCS | shell | guide |
l1-linux-filesystem |
Hiérarchie du système de fichiers Linux (FHS) | l1 | RHCSA · LFCS | shell | guide |
l1-navigate-filesystem |
Naviguer dans le système de fichiers | l1 | RHCSA · LFCS | shell | guide |
l1-paths-absolute-relative |
Chemins absolus et relatifs | l1 | RHCSA · LFCS | shell | guide |
l1-redirections-pipes |
Rediriger les flux et chaîner des commandes avec des pipes | l1 | RHCSA | shell | guide |
l1-grep-regex |
Filtrer un journal avec grep et les expressions régulières | l1 | RHCSA · LFCS | shell | guide |
l1-text-processing |
Transformer et agréger du texte avec cut, sort, uniq, sed et awk | l1 | RHCSA · LFCS | shell | guide |
l1-find-files |
Localiser des fichiers avec find par nom, taille et permissions | l1 | RHCSA · LFCS | shell | guide |
l1-tar-archives |
Archiver, compresser et extraire sélectivement avec tar, gzip et bzip2 | l1 | RHCSA | shell | guide |
l1-permissions-ugo |
Poser les permissions exactes avec chmod (octal et symbolique) | l1 | RHCSA · LFCS | shell | guide |
l1-links-hard-sym |
Créer des liens physiques et symboliques et les distinguer | l1 | RHCSA | shell | guide |
l1-bash-script |
Écrire un premier script Bash : variables, boucle et condition | l1 | RHCSA · LFCS | shell | guide |
l1-git-basics |
Initialiser un dépôt Git : commit, historique et branche | l1 | LFCS | shell | guide |
l1-env-profiles |
Variables d'environnement : export, PATH et un fichier env sourcé | l1 | LFCS | shell | guide |
l1-ssl-certificates |
Inspecter un certificat TLS avec openssl | l1 | LFCS | shell | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
l2-swap-management |
Ajouter et gérer le swap | l2 | RHCSA · LFCS | vm | guide |
l2-fstab-persist-uuid |
Monter un système de fichiers de façon persistante par UUID dans /etc/fstab | l2 | RHCSA · LFCS | vm | guide |
l2-partition-gpt |
Créer des partitions GPT sur un disque avec parted | l2 | RHCSA · LFCS | vm | guide |
l2-filesystem-create-xfs |
Créer et labelliser un système de fichiers XFS, puis le monter | l2 | RHCSA · LFCS | vm | guide |
l2-disk-space-troubleshoot |
Diagnostiquer un système de fichiers plein et récupérer de l'espace | l2 | RHCSA · LFCS | vm | guide |
l2-storage-performance |
Optimiser un montage avec noatime (de façon persistante) | l2 | LFCS | vm | guide |
l2-lvm-extend-persist |
Étendre un volume logique et prouver que le montage survit au reboot | l2 | RHCSA · LFCS | vm | guide |
l2-nfs-mount-persist |
Monter un export NFS de façon persistante depuis un serveur | l2 | LFCS | vm | guide |
l2-autofs-ondemand |
Monter un système de fichiers à la demande avec autofs | l2 | LFCS | vm | guide |
l2-raid-mdadm |
Construire un RAID 1 logiciel avec mdadm | l2 | LFCS | vm | guide |
l2-luks-encryption |
Chiffrer un disque avec LUKS | l2 | RHCSA | vm | guide |
l2-user-lifecycle |
Créer un compte local avec UID, shell et groupes exacts | l2 | RHCSA · LFCS | vm | guide |
l2-password-policy |
Appliquer une politique d'expiration et de complexité des mots de passe | l2 | RHCSA · LFCS | vm | guide |
l2-sudo-delegation |
Déléguer des droits sudo limités via un drop-in sudoers | l2 | RHCSA · LFCS | vm | guide |
l2-acl-posix |
Accorder un accès fin avec les ACL POSIX | l2 | RHCSA · LFCS | vm | guide |
l2-collaborative-setgid |
Mettre en place un répertoire collaboratif avec le bit set-GID | l2 | RHCSA · LFCS | vm | guide |
l2-package-management |
Installer, supprimer et interroger des paquets avec dnf | l2 | RHCSA | vm | guide |
l2-repo-configure |
Configurer un dépôt dnf avec un fichier .repo | l2 | RHCSA | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
l3-boot-target |
Régler la cible de démarrage systemd par défaut | l3 | RHCSA · LFCS | vm | guide |
l3-grub-kernel-args |
Ajouter un paramètre noyau persistant au démarrage | l3 | RHCSA | vm | guide |
l3-service-create-unit |
Créer et activer un service systemd | l3 | RHCSA · LFCS | vm | guide |
l3-service-diagnose |
Diagnostiquer et corriger un service systemd en boucle de crash | l3 | RHCSA · LFCS | vm | guide |
l3-journald-persist |
Rendre le journal systemd persistant au reboot | l3 | RHCSA · LFCS | vm | guide |
l3-scheduling-cron |
Planifier une tâche récurrente avec cron | l3 | RHCSA · LFCS | vm | guide |
l3-scheduling-at |
Planifier une tâche ponctuelle avec at | l3 | RHCSA · LFCS | vm | guide |
l3-scheduling-timers |
Planifier une tâche récurrente avec un timer systemd | l3 | RHCSA · LFCS | vm | guide |
l3-app-constraints |
Régler les limites de ressources par utilisateur (fichiers ouverts) avec limits.d | l3 | LFCS | vm | guide |
l3-sysctl-persist |
Durcir des paramètres noyau durablement avec sysctl.d | l3 | RHCSA | vm | guide |
l3-process-signals-priority |
Abaisser la priorité d'ordonnancement d'un service avec Nice | l3 | LFCS | vm | guide |
l3-tuned-profile |
Appliquer un profil de performance tuned | l3 | RHCSA | vm | guide |
l3-fs-readonly-recover |
Récupérer un montage en lecture seule dû à un fstab cassé | l3 | RHCSA · LFCS | vm | guide |
l3-ssh-access-recovery |
Réparer une configuration sshd cassée avant de perdre la main | l3 | RHCSA · LFCS | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
l4-ntp-sync |
Synchroniser l'horloge avec chrony et fixer le fuseau, durablement | l4 | RHCSA | vm | guide |
l4-network-static-persist |
Configurer une IPv4 statique persistante avec NetworkManager | l4 | RHCSA | vm | guide |
l4-network-troubleshoot |
Diagnostiquer et rétablir une connexion réseau tombée | l4 | RHCSA | vm | guide |
l4-firewall-persist |
Ouvrir un service firewalld de façon permanente | l4 | RHCSA | vm | guide |
l4-ssh-key-auth-harden |
Mettre en place un accès SSH par clé durci pour un utilisateur de service | l4 | RHCSA | vm | guide |
l4-podman-basic |
Lancer un conteneur détaché avec Podman | l4 | RHCSA | vm | guide |
l4-podman-systemd-persist |
Faire tourner un conteneur en service systemd avec Quadlet (persistant au boot) | l4 | RHCSA | vm | guide |
l4-podman-images |
Gérer les images de conteneurs : pull, tag, save et inspection | l4 | RHCSA | vm | guide |
l4-selinux-boolean-port |
Autoriser un service avec SELinux : booléen persistant et port étiqueté | l4 | RHCSA | vm | guide |
l4-selinux-context-fix |
Corriger le contexte SELinux d'un fichier, durablement | l4 | RHCSA | vm | guide |
l4-selinux-diagnose-avc |
Diagnostiquer un refus SELinux (AVC) et le corriger proprement | l4 | RHCSA | vm | guide |
l4-nat-portforward |
Mettre en place une redirection de port NAT persistante avec nftables | l4 | RHCSA | vm | guide |
l4-ldap-integration |
Authentifier Linux sur un annuaire LDAP avec SSSD | l4 | RHCSA | vm | guide |
l4-reverse-proxy-lb |
Répartir la charge d'un backend web avec HAProxy | l4 | LFCS | vm | guide |
l4-bridge-bonding |
Agréger des liens : un bond active-backup sous un bridge avec nmcli | l4 | LFCS | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
ebpf-tracer-bcc |
Démasquer un processus mystère avec les outils de traçage eBPF | l4 | - | vm | guide |
ebpf-durcir-sysctl |
Durcir eBPF avec sysctl : fermer l'accès aux utilisateurs et rendre le réglage durable | l4 | - | vm | guide |
ebpf-inventaire-bpftool |
Inventorier les programmes eBPF chargés avec bpftool et arrêter le service qui en porte un | l4 | - | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
lfcs-package-apt |
Gérer les paquets Debian avec apt et dpkg | l2 | LFCS | vm | guide |
lfcs-firewall-ufw |
Ouvrir un service dans le pare-feu avec ufw | l4 | LFCS | vm | guide |
lfcs-apparmor |
Gérer un profil AppArmor : le passer en mode complain | l4 | LFCS | vm | guide |
lfcs-netplan-static |
Configurer une IP statique et une route avec netplan | l4 | LFCS | vm | guide |
lfcs-storage-quotas |
Activer les quotas utilisateur XFS et imposer une limite | l2 | LFCS | vm | guide |
lfcs-mount-cifs |
Monter un partage SMB/CIFS de façon persistante et sûre | l2 | LFCS | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
drill-essential-commands |
Drill : commandes essentielles en conditions d'examen | l1 | RHCSA · LFCS | vm | guide |
drill-users-groups |
Drill : utilisateurs, groupes et délégation en conditions d'examen | l2 | RHCSA · LFCS | vm | guide |
drill-systemd |
Drill : unités systemd, timers et planification en conditions d'examen | l3 | RHCSA · LFCS | vm | guide |
drill-storage |
Drill : partitions, LVM et swap en conditions d'examen | l2 | RHCSA · LFCS | vm | guide |
drill-packages |
Drill : gestion des paquets en conditions d'examen | l2 | RHCSA · LFCS | vm | guide |
drill-firewall |
Drill pare-feu en conditions d'examen | l4 | RHCSA · LFCS | vm | guide |
drill-selinux |
Drill SELinux en conditions d'examen | l4 | RHCSA | vm | guide |
drill-apparmor |
Drill AppArmor en conditions d'examen | l4 | LFCS | vm | guide |
drill-network |
Drill : réseau statique en conditions d'examen | l4 | RHCSA · LFCS | vm | guide |
| Lab (id) | Titre | Niveau | Certif | Runtime | Guide compagnon |
|---|---|---|---|---|---|
capstone-mise-en-production |
Mettre un serveur en production : une mission, neuf livrables, un redémarrage | l2 | RHCSA · LFCS | vm | guide |
capstone-serveur-casse |
Serveur cassé : le site ne répond plus, le symptôme ne dit rien | l3 | RHCSA | vm | guide |
rhcsa-mock-exam |
Examen blanc RHCSA EX200 (20 tâches sur 2 VM) | l2 | RHCSA | vm | guide |
lfcs-mock-exam |
Examen blanc LFCS (17 tâches sur Ubuntu 24.04) | l2 | LFCS | vm | guide |
89 labs, table générée par scripts/gen_catalog.py.
- Contribuer : voir CONTRIBUTING.
- Conduite : Code de conduite · Sécurité : SECURITY.
- Versions : RELEASING (bundles tar.gz, pas de PyPI).
- Licence : CC BY 4.0.
Copyright (c) 2026 Stéphane Robert, https://www.stephane-robert.info
Ce catalogue est publié sous licence Creative Commons Attribution 4.0 International (CC BY 4.0). Vous pouvez le partager et l'adapter, y compris commercialement, à une condition : créditer Stéphane Robert, lier le blog, et indiquer si vous avez modifié le contenu, sans laisser entendre que l'auteur approuve votre usage.
Le fichier LICENSE ne contient que le texte officiel de la licence, sans
en-tête ajouté : c'est ce qui permet à GitHub de la reconnaître.