This repository is a lab catalog consumed by the
dsoxlab CLI. Contributions are new
labs, fixes, and translations. The CLI itself lives in its own repository — do
not add engine code here.
uv tool install dsoxlab # the CLI (external tool)
git clone <this-repo-url> linux-dsoxlab-training
cd linux-dsoxlab-training
dsoxlab doctor # check your environmentA lab's tests must assert the state of the system, never that a command was
typed. The service is running and enabled; the mount is present and declared
in /etc/fstab by UUID; the SELinux context is set persistently. Whenever a lab
configures something meant to survive a reboot, the tests assert
persistence after reboot explicitly — it is exactly what fails RHCSA
candidates.
labs/linux/<section>/<lab>/
├── lab.yaml # the contract (id, level, runtime, validation…)
├── lab.fr.yaml # optional: French override of title/description ONLY
├── README.md / scenario.md
├── setup.yaml / cleanup.yaml # VM labs
└── challenge/
├── README.md # the mission, no step-by-step
├── hints.yaml # cost-weighted hints
├── tests/test_functional.py # the proof: system state
└── work/ # starting material (shell labs)
solution/… # reference solution, replayed in CI to prove itself
- Start from a capability, not a guide. Describe a demonstrable capability ("extend a logical volume and prove the mount survives a reboot"), open an issue, and agree on scope before writing.
- Pick the runtime the subject demands: VM (
kvm/incus) for anything touching systemd, the firewall, SELinux, boot, or persistent storage;shellfor files, text, and permissions. - Point
doc_urlat the real guide the lab makes the learner practice.
dsoxlab validate-structure # the meta.yml + lab.yaml contract
dsoxlab check <lab-id> # run the lab's tests (or: pytest)
python3 scripts/gen_catalog.py # refresh the README catalog (labs + guide URLs)Required before every push: the root README.md and README.fr.md must
list every lab together with its companion-guide URL. The catalog is generated
from the real lab.yaml files — run python3 scripts/gen_catalog.py after
adding or renaming a lab, and python3 scripts/gen_catalog.py --check to verify.
CI and the pre-push hook both reject a stale catalog.
python3 scripts/valider-labs.py --lab <id> requires a lab to score 0 before
any work and 100 after the reference solution, and records the verdict
in validation-labs.json. For a VM lab, it first brings its machines back to a
frozen base: otherwise the first check would also grade whatever earlier
labs left on the same VMs.
That base is frozen once, on fresh VMs, and again after every provision,
which recreates the domains:
dsoxlab destroy --yes && dsoxlab provision
bash scripts/rebase-vms.sh # about 2 min; a reset then takes ~6 sWithout a valid base, the validator refuses to run the lab and says why.
- Lab id:
<level>-<slug>(e.g.l1-first-terminal), matching the directory name. - Commits:
feat(<lab>): …,fix: …,docs: …,test: …. - i18n:
lab.fr.yamloverridestitleanddescriptiononly — nothing else.
Work on a dedicated branch, keep dsoxlab validate-structure green, write a
clear description, and link the capability/issue it addresses.