The single template for every CyberCTF lab. A lab is described once in isoloom.yml
(Isoloom): its machines, their network and services, and how each
machine is produced as a container and as a VM. isoloom generate writes the files for every
target under .isoloom/ (Docker Compose, Vagrant, Terraform), and the CyberCTF launcher runs
them wherever the player chooses: Docker on their machine, local VMs, their own server (ESXi,
Proxmox), any cloud, or hosted. Use AGENTS.md and rules/ as the single source of truth for
requirements.
A complete lab built this way: CyberCTF/invoice-portal-api.
isoloom.yml: the lab (start fromisoloom.yml.example)build/<machine>/: each container machine'sDockerfileandsrc/(settings asENVin the Dockerfile: Isoloom passes no environment besides the lab's inputs)provision/<machine>.sh: the same machine as a VM (Debian by default), run as root from/opt/isoloomchecks:inisoloom.yml: declared probes (http,tcp) for what the spec can't know, andbuild/check/check.shfor what only a program can tell (the intended path still works), run from the player's side byisoloom test; reachability checks are derived from the speccommon:: what every machine shares (the VM box, the size);message:: shown when the lab is upevidence/claim-evidence.sh: claims the player's evidence with the launch token; copy it next to the machine that holds the evidence (seerules/apps/run/EVIDENCE-INJECTION.md).isoloom/: generated, committed, never edited (CI fails when it's out of date)tests/: pytest suite against.isoloom/docker/compose.yml.ctf/: planning and metadata (SCENARIO, EVIDENCE, metadata.json)
isoloom run docker # generate, build and start (prints the lab's message)
isoloom test docker # the lab's checks, plus the ones Isoloom derives from the spec
isoloom connect web # a shell on a machine
isoloom down dockerVMs: isoloom run vagrant. Install Isoloom from the
releases or
curl -fsSL https://raw.githubusercontent.com/isoloom/isoloom/main/install.sh | sh.
Some labs are VM-only: a multi-VM Windows Active Directory range has no container form. Describe it the same way, with these differences:
- Machines carry only
vm:(nodocker:):os: windows-server-2019(or another), and a per-machineprovision:step that only sets up WinRM so the controller can reach them. - The lab is provisioned at the environment level: a top-level
provision:step points at an Ansible playbook with itsrequirements:and inventorygroups. Isoloom brings up a small Debian controller that installs Ansible, generates the inventory (hosts, addresses, WinRM), and runs the playbook against the Windows machines over WinRM. - No
build/, no container evidence injection, notests/(those run against the Docker edition, which a VM-only lab does not have). Keep only the provisioning and theisoloom.yml. - CI covers it without running it: the
isoloomjob validates the spec and that.isoloom/is current,vagrantparses the Vagrantfiles,terraformvalidates the generated modules; the livelabjob is skipped (nocompose.yml). A multi-VM Windows range cannot run in a CI runner, so it is verified by generation, not by a live boot.
- Every machine gets
docker:andvm:when it can, so the lab runs on every target. - A service listens on the port its machine declares;
publish:exposes one to the player. - DB init: numbered SQL files; create the user before GRANT; separate DB and global privileges.
- Package managers match the base image (Debian: apt-get, Alpine: apk, Oracle: microdnf).
- Evidence: never hard-coded. Claimed into a machine volume (the token is single-use), placed by
a
docker.initscript and by the VM's provision step.
validate.yml checks the spec, that .isoloom/ is current, runs the lab with isoloom test, and
validates every Vagrant and Terraform output. publish.yml registers the lab with CyberCTF through
the shared, hardened CyberCTF/publish-lab-action (the backend endpoints live in that private
action, not here) and waits for a maintainer to approve it via the production environment, so a
push alone never publishes. Both skip the template itself (no isoloom.yml yet).
Per lab repo, set up once: a production environment with required reviewers, and the
organization secrets CYBERAUTH_CLIENT_ID / CYBERAUTH_CLIENT_SECRET scoped to it.