I am Stéphane ROBERT, infrastructure engineer at LINAGORA, working from Yffiniac in Brittany, France.
I spend my days hardening pipelines and my evenings writing about it. Everything I learn ends up in one of two places: a free tutorial on my blog, or a lab you can actually run from one of the repositories below. Nothing here is a demo that only works on my laptop.
Four tools, each one because the existing answer did not hold up.
| 🎭 | feint | the Scaleway, Outscale and Exoscale APIs, on your laptop | |
| 🧪 | dsoxlab | hands-on DevSecOps labs that grade the machine, not your typing | |
| 🛰️ | pepin | three sovereign clouds, one axis | |
| 🛡️ | pavois | Linux compliance that reads the running config, not the files |
The problem: testing cloud automation needs a real account, real credentials and a real bill. And a pipeline that needs secrets cannot run on a pull request from a fork, which is where the contributions come from.
feint is a local emulator of three cloud APIs. It is not a mock written against the documentation: the vendors' own official CLIs drive it end to end, and Terraform and OpenTofu drive two of the three. If scw, osc-cli or exo cannot tell the difference, neither can your automation.
- No account, no credentials, nothing billed. It runs offline, on a laptop, in CI, on a plane.
- Driven by the real clients. Conformance is proven by the vendors' CLIs, not by assertions about them.
- Ships where you already are. A GitHub Action and a Homebrew tap whose formula is derived from each release's signed checksums, never written by hand.
feint up # three cloud APIs, locally
scw instance server list # the vendor's own CLI, unmodified
terraform apply # against the emulator, nothing billedThe problem: most hands-on labs grade you on the commands you typed. Real exams, RHCSA and LFCS, grade the state of the machine, after a reboot. That gap is exactly where candidates fail.
dsoxlab is a domain-agnostic CLI framework driving training labs that live in their own repositories. Each catalog declares itself through a root meta.yml and one lab.yaml per lab, so adding a domain means writing a file, not patching the engine.
- Validation proves, it does not trust. Labs are graded on the actual state of the system with
pytest-testinfra, including persistence after reboot. - Three runtimes. A plain shell, an Incus container, or a full KVM/libvirt virtual machine, chosen per lab.
- Progress that sticks. Scores, hint costs and history persisted in a local SQLite database, XDG-compliant.
- Bilingual by design. Every user-facing string ships in English and French (
DSOXLAB_LANG=en|fr).
uv tool install dsoxlab
dsoxlab doctor # diagnoses (and repairs) the local toolchain
dsoxlab list-labs # the catalog is detected from the repo's meta.ymlThe problem: every provider ships its own posture dashboard, so three clouds means three scores that cannot be compared, and a question nobody can answer: which of them is actually the worst?
pepin evaluates Outscale, Scaleway and Exoscale against one baseline, anchored on SCSL, SecNumCloud, CIS and ISO. One axis, three clouds, so the comparison means something.
- Before it is provisioned, not after it is billed. It reads a Terraform plan, so a misconfiguration is caught at review time.
- Sovereign by construction. No dependency on a US-hosted control plane to tell you how your European cloud is doing.
- One baseline, not a crosswalk. A control is mapped to the texts it really cites, and never invented to fill a table.
pepin scan --provider outscale # posture of a live account
pepin scan --tf plan.json # or of a plan, before applyThe problem: /etc/ssh/sshd_config can say PermitRootLogin no while a drop-in read later sets it to yes. Every file-based scanner reports the host compliant. The machine accepts root over SSH.
pavois asks the service instead of reading its files: sshd -T, sysctl, systemctl show, auditctl -l. The effective configuration, which is the only one an attacker meets. 789 controls across 9 Linux targets, graded A to E over CIS, ANSSI-BP-028, NIST, PCI-DSS and DISA STIG.
- It hardens, and proves it.
harden apply --rebootcompares the kernelboot_idbefore and after, so a setting that only holds until the next boot cannot pass silently. - Evidence you can hand to an auditor. A campaign packages into a tamper-evident bundle you sign under your own identity; pavois never holds a key.
- Proven, not asserted. Debian 12 and 13 go through the full campaign on fresh VMs, and the run itself is validated: a control that returned a verdict it never measured fails the campaign.
pavois scan local --sudo # grade this host, A to E
pavois harden plan admin@server1 # a reviewable plan, nothing applied
pavois bundle before.json after.json # signable evidenceFree, in French, and updated far more often than this README. Roughly a hundred articles and a full DevOps course live at www.stephane-robert.info.
- Transformer ce site en vraies formations, pas en tas de guides 2026-10-23
- Du site de formations au parcours par compétences : où j'en suis 2026-10-08
- Une roadmap publique pour maintenir mes formations avec vous 2026-09-17
- npm ne lance plus les scripts d'installation : pnpm l'avait fait avant 2026-07-28
- Quand vos dépôts GitHub deviennent l'infrastructure d'attaque d'un autre 2026-07-23
- scankit
Go— Shared Go library: terminal presentation, SARIF, findings and A-E scoring for security tooling - secure-python-pipeline
Python★ 4 — Lab : API Python avec pipeline CI/CD securise (supply chain, SLSA, SBOM, cosign)
17 catalogs, 480 labs. Self-hosted, runnable, no signup wall, no SaaS. Every one of them is driven by dsoxlab and graded the way the real exams grade: on the state of the machine after a reboot, not on the commands you typed.
| Catalog | Labs | What it covers |
|---|---|---|
| ansible-training ★ 119 | 113 | Lab pédagogique public de la formation Ansible RHCE EX294 2026. |
| terraform-dsoxlab-training ★ 28 | 91 | Lab pédagogique public de la formation Terraform (parcours du blog). |
| linux-dsoxlab-training ★ 45 | 89 | Plateforme de labs pédagogiques pour la formation Linux du blog Stéphane Robert. |
| kubernetes-dsoxlab-training ★ 6 | 64 | Labs vérifiables pour la formation Kubernetes du blog Stéphane Robert. |
| gitlab-ci-dsoxlab-training | 29 | Hands-on lab catalog. |
| bdd-dsoxlab-training | 17 | Labs PostgreSQL et MySQL pour dsoxlab : installer, piloter, configurer, securiser, sauvegarder, observer, restaurer et repliquer une instance. |
| iam-dsoxlab-training | 16 | Les labs de la formation « Gestion des identités et des accès ». |
| devsecops-dsoxlab-training | 13 | Un seul projet, notes-api, durci version après version au fil de la formation DevSecOps |
| artefacts-dsoxlab-training | 11 | Labs Depots d'artefacts pour dsoxlab : heberger un depot, relayer un index public, publier ses paquets, servir des images, signer et restaurer. |
| dev-pour-ops-dsoxlab-training | 10 | Une initiation au développement pour les Ops, en Python. |
| mlops-dsoxlab-training | 7 | Labs MLOps pour dsoxlab : rendre un entrainement reproductible, versionner les donnees, tracer un modele et le designer par alias. |
| python-dsoxlab-training | 7 | Le Python qu'un ingénieur DevOps ou DevSecOps écrit chaque semaine |
| cicd-dsoxlab-training | 5 | Les labs de la formation « Introduction aux pipelines CI/CD » du blog, joués SANS AUCUN COMPTE sur une forge locale (Forgejo et son runner) dans une VM du lab. |
| cloud-dsoxlab-training | 4 | Labs de la formation Cloud du blog, joués sans compte cloud ni carte bancaire. |
| publier-service-dsoxlab-training | 2 | Labs Publier un service pour dsoxlab : un reverse proxy devant ses services, avec des certificats obtenus automatiquement. |
| containers-dsoxlab-training | 1 | Labs vérifiables de la formation Conteneurisation du blog. |
| github-actions-training ★ 7 | 1 | Un lab par compétence du parcours GitHub Actions du blog. |
This list is not maintained by hand: build.py calls a repository a catalog when it carries the contract's root meta.yml, and counts its labs/**/lab.yaml. A catalog published today appears here tomorrow, and one that is emptied leaves on its own.
| Infrastructure as code | Terraform · OpenTofu · Pulumi · Packer · Vagrant |
| Configuration | Ansible · Chef / CINC · InSpec |
| Runtime | Kubernetes · Talos · K3s · Docker · Incus · KVM/libvirt |
| CI/CD | GitHub Actions · GitLab CI · Dagger |
| Supply chain | SLSA · SBOM · Cosign · Sigstore · Trivy · OpenSSF Scorecard · Semgrep |
| Observability | Prometheus · Grafana · Loki |
| Languages | Python · Go · Shell · HCL |
| Cloud | Scaleway · Outscale · Exoscale · AWS · GCP |
Why this page has no stats widget
Because the popular ones stopped working. github-readme-stats has been returning HTTP 503 since June 2026 and is no longer maintained; github-profile-trophy answers 402 and now relies on sixteen volunteer mirrors. Thousands of profiles are quietly displaying broken images right now — including, at the time of writing, its own author's.
Everything on this page is either a static SVG committed in this repository or a shields.io badge reflecting real state: a CI run, a release tag, an OpenSSF Scorecard rating. The counters at the top are computed from the GitHub API by build.py and committed by a scheduled workflow.
On a profile about supply chain security, not hotlinking someone else's free Vercel deployment seemed like the least I could do.
Rendered by build.py from README-TEMPLATE.j2 · refreshed daily by GitHub Actions





