← Home

Getting started

One-time setup on Linux, on Windows through WSL2, or on a Mac inside a small Linux VM. It takes ten to twenty minutes; longer the first time on a machine that has never had WSL2 or a VM. After this, every lab is a single command.

Quick start

The whole setup in four steps. Each one links to the detail below.

  1. Install Docker
  2. Install Containerlab
  3. Download a lab
  4. ./labctl deploy

What you need

Install

Three tracks. Pick the one that matches the machine in front of you. All three end up at the same place: a Linux shell with Docker and Containerlab on it.

Linux Windows (WSL2) Mac (Multipass)

Docker Desktop is not required on any track. Containerlab starts FRR as a plain container from the command line.

Linux

Ubuntu 22.04 or 24.04 is the tested path.

  1. Docker
    curl -fsSL https://get.docker.com | sudo sh
    sudo usermod -aG docker $USER

    On WSL2 the script prints WSL DETECTED: We recommend using Docker Desktop and then sits still for about twenty seconds. That is a notice, not an error. Leave it running (do not press Ctrl+C) and the install carries on and completes on its own. Docker Desktop is not needed.

  2. Refresh your group membership

    The usermod line only takes effect in a new session, so the shell you ran it in still cannot reach Docker.

    Linux: log out and back in.

    WSL2: run wsl.exe --shutdown (from the Ubuntu window or PowerShell), then reopen Ubuntu from the Start menu.

    Mac (Multipass): type exit, then run multipass shell labs again.

    Confirm it took effect:

    docker ps

    An empty table is the right answer. If it reports permission denied, the refresh has not happened yet. Either redo the step above, or run newgrp docker as a one-time shortcut for the current shell.

  3. Containerlab
    bash -c "$(curl -sL https://get.containerlab.dev)"

    Confirm with containerlab version.

  4. Pull the router image once
    docker pull quay.io/frrouting/frr:10.4.5

    Every lab uses this same image, so this is the only download.

  5. tmux and unzip
    sudo apt install -y tmux unzip

    ./labctl tabs uses tmux to open one window per router in a single command. Without tmux the labs still run, but you would be opening those terminals yourself. unzip opens the lab zips; a fresh Ubuntu, on WSL2 or in a VM, often does not have it.

Windows (WSL2)

WSL2 runs a real Linux kernel, so Docker and Containerlab behave as they do on a Linux host. Ten to twenty minutes end to end; longer the first time on a machine that has never had WSL2 or a VM.

  1. Enable the Windows features

    1a. Confirm virtualization is on: Task Manager, Performance, CPU. The bottom right should read "Virtualization: Enabled." If it says Disabled, enable Intel VT-x or AMD SVM in the BIOS/UEFI first; WSL2 cannot run without it.

    1b. Open Start, type "Turn Windows features on or off," open it, and check both "Virtual Machine Platform" and "Windows Subsystem for Linux." Click OK and let it finish.

    1c. Restart the computer. Use Restart, not Shut down; Shut down with Fast Startup does not apply feature changes. This is the only reboot needed.

  2. Install Ubuntu

    2a. Open PowerShell as administrator and run:

    wsl --install -d Ubuntu

    It downloads Ubuntu and, in the same window, asks you to create a Unix username and password. Pick anything; it is separate from your Windows login.

    2b. Ubuntu asks whether to opt in to metrics collection. Answer n. It has no effect on the labs.

    2c. The prompt now shows a Linux path under /mnt/c. Type cd ~ to move to your Linux home folder; the prompt should end in ~$. Do all later steps from here.

    2d. From now on, Ubuntu is in the Start menu. Open it from there for future sessions; PowerShell is not needed again.

    If 2a instead prints a message about enabling a component and rebooting, Restart once more and run the command again.

  3. Enable systemd

    Docker runs natively under systemd. Inside Ubuntu, create /etc/wsl.conf:

    sudo tee /etc/wsl.conf >/dev/null <<'EOF'
    [boot]
    systemd=true
    EOF

    Then shut WSL down so the setting takes effect. This works from the Ubuntu window or from PowerShell:

    wsl.exe --shutdown

    It closes the Ubuntu window. Reopen Ubuntu from the Start menu before continuing.

  4. Follow the Linux steps

    Inside Ubuntu, work through the five Linux steps above: Docker via get.docker.com, the group refresh, Containerlab, the FRR image pull, and tmux with unzip. The WSL2 notes in those steps are written for this track.

If you use the Windows Terminal app, setting Ubuntu as its default profile (Settings, Startup) makes new tabs open in Linux. Not required; ./labctl tabs handles multiple windows for you.

Mac (Multipass)

The labs run on Linux, so on a Mac they run inside a small Ubuntu VM that Multipass creates. Do not run the Linux track's commands on macOS itself: the Docker install script refuses macOS, and usermod does not exist there. Ten to twenty minutes end to end; longer the first time on a machine that has never had WSL2 or a VM.

  1. Check your macOS version

    Apple menu, About This Mac. Multipass needs macOS 13.3 or later. If yours is older, open System Settings, General, Software Update (System Preferences, Software Update on macOS 12 and earlier) and update first; the Multipass installer refuses to run on an older version.

    If your Mac cannot update to 13.3, use UTM instead: create an Ubuntu Server VM with 2 CPUs, 4 GB memory and a 20 GB disk, then follow the Linux track inside it. The rest of this track is for Multipass.

  2. Install Multipass

    Download the macOS installer from multipass.run and run it. Homebrew users can install it this way instead; Homebrew is not required:

    brew install --cask multipass

    Close and reopen Terminal afterward.

  3. Create the VM
    multipass launch --name labs --cpus 2 --memory 4G --disk 20G

    The first run downloads Ubuntu and takes a few minutes.

  4. Open a shell in it
    multipass shell labs

    The prompt becomes ubuntu@labs. You are now on Linux: follow the Linux track from its step 1. For the group refresh in step 2, type exit and run multipass shell labs again.

  5. Run multipass on the Mac, never in the VM

    Every multipass command runs in the Mac's own Terminal, at the prompt that shows your Mac's name, never at ubuntu@labs. With the VM shell open, use a second Terminal window for them. Never put sudo in front of multipass: it breaks authentication with the Multipass service.

  6. Get a lab into the VM

    The browser saves the download on the Mac, where the VM cannot see it, and Safari usually unzips it as it arrives. From a Mac Terminal (not inside the VM), see which you have:

    ls ~/Downloads | grep lab-01

    If it shows a folder, lab-01-area-boundary-trap, copy the folder into the VM:

    multipass exec labs -- mkdir -p /home/ubuntu/labs
    multipass transfer -r ~/Downloads/lab-01-area-boundary-trap labs:/home/ubuntu/labs/

    If it shows the zip, lab-01-area-boundary-trap.zip, copy the zip into the VM:

    multipass transfer ~/Downloads/lab-01-area-boundary-trap.zip labs:/home/ubuntu/

    then unzip it inside the VM. This needs unzip, which the Linux track's step 5 installs:

    mkdir -p ~/labs && mv ~/lab-01-area-boundary-trap.zip ~/labs/ && cd ~/labs && unzip lab-01-area-boundary-trap.zip

    Either way the lab is now in ~/labs inside the VM: cd into its folder and run ./labctl deploy, as in Run a lab. For the paid pack, grep for adjacency and use routing-pack-1 or routing-pack-2 in place of lab-01-area-boundary-trap.

    On UTM, share the Mac's Downloads folder with the VM and mount it inside the VM as UTM's Linux guide describes, then copy the zip from that mount.

  7. Later sessions

    From a Mac Terminal, start the VM if it was stopped, then open a shell in it:

    multipass start labs
    multipass shell labs

    When you are finished, tear down any running lab with ./labctl destroy, then from a Mac Terminal:

    multipass stop labs

Run a lab

Every lab, free or paid, arrives as a zip. Get Lab 01 free here and the paid pack arrives by email after purchase.

Download the zip in your browser, then move it into the Linux home folder and unzip it. Pick your platform:

mkdir -p ~/labs creates the folder the first time; it's harmless afterward.

Windows (WSL2)

mkdir -p ~/labs && cp /mnt/c/Users/<your-windows-name>/Downloads/lab-01-area-boundary-trap.zip ~/labs/ && cd ~/labs && unzip lab-01-area-boundary-trap.zip

Linux

mkdir -p ~/labs && mv ~/Downloads/lab-01-area-boundary-trap.zip ~/labs/ && cd ~/labs && unzip lab-01-area-boundary-trap.zip

Mac (Multipass), first from a Mac Terminal, see whether Safari unzipped the download:

ls ~/Downloads | grep lab-01

If it shows a folder, copy the folder into the VM:

multipass exec labs -- mkdir -p /home/ubuntu/labs
multipass transfer -r ~/Downloads/lab-01-area-boundary-trap labs:/home/ubuntu/labs/

then inside the VM, cd ~/labs.

If it shows the zip, copy the zip into the VM:

multipass transfer ~/Downloads/lab-01-area-boundary-trap.zip labs:/home/ubuntu/

then inside the VM:

mkdir -p ~/labs && mv ~/lab-01-area-boundary-trap.zip ~/labs/ && cd ~/labs && unzip lab-01-area-boundary-trap.zip

Labs must live under the Linux home (~/labs), not under /mnt/c or the Mac filesystem. Windows-mounted paths carry no Unix file permissions, so labctl arrives without its executable bit and will not run, and they are markedly slower to run from. On a Mac, the containers run inside the VM and cannot see the Mac's folders at all.

Then start it:

cd lab-01-area-boundary-trap
./labctl deploy

The lab is now running. Open lab.html inside the lab folder in a browser for the topology, the symptom, the investigation questions, and the reveal for when you have a theory, then come back to the terminal to work it. It needs no network, and every lab has one. Lab 01 also has a public page, the Lab 01 page, with its topology and symptom. From WSL2, explorer.exe . opens the lab folder in Windows; on a Mac, multipass transfer the lab.html back out, or read scenario.md in the terminal.

If ./labctl reports Permission denied, run chmod +x labctl once. Some Windows unzip tools drop the executable bit, and a copy through /mnt/c always does.

Each lab folder has the same launcher with the same commands:

./labctl deploy     # bring it up and apply the scenario
./labctl tabs       # open a window per router in tmux
./labctl status     # neighbor state and routes at a glance
./labctl sh r2      # a Linux shell on that router
./labctl verify     # check your fix
./labctl reset      # back to the broken starting state
./labctl destroy    # tear it down

Paid pack

The pack arrives the same way as the free lab, as a download link in the Gumroad email. Copy it into ~/labs and unzip it exactly as above, with the pack's zip name. It unzips to one folder holding all ten labs; cd into any of them and run ./labctl deploy. Every lab inside it uses the same ./labctl commands shown above.

Working the lab

Every lab is easier with one terminal per router, and one more in the lab folder for the launcher. ./labctl tabs lays that out in one command:

./labctl tabs

It opens a tmux session named after the lab: one window per router, each already inside that router's vtysh, and a last window named ctl in the lab folder for status, verify and reveal. Run it again at any point and it reattaches to the session you left rather than building a second one.

The bar along the bottom lists the windows (1:r1* 2:r2 3:r3 4:ctl), and the asterisk marks the one you're in. To switch, press Ctrl+B, release both keys, then press the key that follows it:

Ctrl+B, then 2                 switch to r2 (any window number works)
Ctrl+B, then n / p             next / previous window
Ctrl+B, then w                 pick a window from a list
Ctrl+B, then d                 detach, leaving the lab running

./labctl tabs reattaches to the session you left.

Detaching leaves every router where you left it, so you can close the terminal, come back later, and pick the same session up mid-investigation. The point of the layout is to keep the router where the symptom shows in a window of its own, so you can re-run a command there without losing whatever you are reading on another router.

The session belongs to the lab, and ./labctl destroy closes it along with the containers. Run destroy from the ctl window and it leaves the session standing, since that is the shell you are typing in; detach first, or close it afterwards with tmux kill-session -t <lab-name>. If a session is ever left behind without its routers, ./labctl tabs rebuilds it rather than dropping you into the remains.

Each lab's scenario.md names the windows that topology needs. The same folder also has lab.html (the scenario with its diagram, readable in a browser with no network), and ./labctl reveal prints the concept and the fix once you have a theory.

Working in vtysh

FRR's shell is modeled on IOS. Get into a router with:

docker exec -it clab-<lab-name>-r1 vtysh

Many familiar operational commands work much as you'd expect:

show ip route
show ip ospf neighbor
show ip ospf database
show ip bgp summary
show running-config
configure terminal

The differences you'll notice: interfaces are named eth1, eth2 rather than GigabitEthernet; prefixes use CIDR (10.0.0.0/24) rather than wildcard masks; and in BGP, neighbors are activated under address-family ipv4 unicast. That's about the whole list for OSPF and BGP work.

The Linux side of the router

One structural difference is worth knowing before it surprises you. On a traditional platform the router owns the whole box. FRR is a routing daemon running on Linux, so the protocol is one layer and the platform is another: anything OSPF or BGP configures lives in vtysh, while properties the kernel owns (interface MTU is the one the labs run into) are reported by vtysh but changed outside it. That split is not a quirk of these labs; it is how white-box switches, SONiC and cloud routers all work.

The launcher opens that shell for you, so there is no container name to remember:

./labctl sh r2

ip, ping, ss and vtysh are all on the PATH there, and exit brings you back to the lab folder. Where a lab's fix needs it, ./labctl reveal says so and spells out the command.

If something's off

Start with the free lab