Back to Blog
★★Intermediate⚙️ Operations
CiscoCMLVIRLNetwork LabSimulationCCNPLab Setup

Setting Up Cisco CML 2.x: A Practical Lab Guide

April 7, 2026·10 min read

Overview

Cisco Modeling Labs (CML) — formerly VIRL — is Cisco's official network simulation platform. Unlike GNS3 or EVE-NG, CML ships with Cisco-supported node images and a RESTCONF/pyATS API that integrates directly into Cisco's DevNet toolchain. If your network is Cisco-heavy, CML is the most frictionless way to build accurate, production-representative topologies.

CML 2.x is a complete rewrite from VIRL 1.x. It runs as a single Linux VM, exposes a browser-based canvas, and supports topology-as-code via YAML files. You can script topology creation, start/stop labs, and extract device configs entirely through the API — no GUI required for automation.

This guide covers a full CML 2.x deployment on VMware ESXi with external network access, image management, and a first working topology.


// CML 2.x Deployment Architecture ESXi HOST CML VM Ubuntu 20.04 16 vCPU / 32GB 500GB NVMe Web UI :443 REST API :443 Console :9000+ SIMULATED TOPOLOGY IOSv R1 IOSv R2 ASAv FW IOSvL2 SW External Connector NETWORK Internet Corp LAN Engineer Browser / SSH

Server Requirements

CML 2.x runs as a single Ubuntu-based VM. The hardware you allocate directly determines how many nodes you can run simultaneously.

ResourceMinimumRecommendedHeavy Use (20+ nodes)
vCPU8 cores (VT-x required)16 cores32 cores
RAM16 GB32 GB64 GB+
Disk200 GB500 GB SSD1 TB NVMe
Network1 NIC (management)2 NICs (mgmt + bridge)2+ NICs, 10GbE
HypervisorVMware Workstation 16+VMware ESXi 7.0+Bare metal Ubuntu 20.04

Nested virtualization is mandatory. CML uses KVM/QEMU internally. On VMware, enable "Expose hardware-assisted virtualization to the guest OS" in the VM CPU settings. Without this, QEMU nodes will fail to start or run at unusable speed.

Each node type has a different memory footprint:

Node TypeRAM per InstancevCPU per InstanceBoot Time
IOSv (router)512 MB1~60 sec
IOSvL2 (switch)768 MB1~90 sec
CSR 1000v3 GB2~3 min
IOS XRv 900016 GB4~8 min
NX-OSv 90008 GB4~5 min
ASAv2 GB1~3 min
Ubuntu Server512 MB1~30 sec

Installation

Step 1 — Download the OVA

Download the CML 2.x OVA from software.cisco.com. You need a valid Cisco account. The file is approximately 3–4 GB depending on the version.

There are two editions:

  • CML Personal — up to 20 nodes, single user, lower-cost license
  • CML Enterprise — unlimited nodes, multi-user, SSO support, HA option

Step 2 — Deploy on VMware ESXi

# ESXi Web UI → Virtual Machines → Create/Register VM → Deploy OVF/OVA
# Select the downloaded .ova file
# Map datastore to your SSD/NVMe datastore
# Map network: NIC 1 → management VLAN, NIC 2 → bridge/external VLAN

# After import — BEFORE powering on:
# Edit VM settings:
#   CPU → check "Hardware virtualization: Expose VMX to guest"
#   RAM → allocate per table above (recommend 32 GB minimum)
#   Disk → expand to 500 GB if needed (thin provision)

Step 3 — First Boot Setup

On first boot CML presents an interactive setup wizard via console. After that it boots into a headless Linux VM.

# Open VM console in ESXi Web UI
# The setup wizard asks for:
#   - Hostname (e.g. cml.bracuso.com)
#   - Management IP, subnet, gateway, DNS
#   - admin password
#   - sysadmin password (OS-level account)

# After setup completes you can reach CML at:
https://<your-cml-ip>
# Default credentials: admin / <password you set>

# SSH access for troubleshooting:
$ ssh sysadmin@<cml-ip>
# sysadmin account gives you the underlying Ubuntu OS

Licensing

CML 2.x uses Smart Licensing. Without an active license, the platform runs in "unlicensed" mode — the UI loads but you cannot start nodes.

# Navigate to: Tools → Licensing in the CML web UI
# Option 1: Smart Licensing (requires internet access from CML VM)
#   Enter your Smart Account token from software.cisco.com

# Option 2: Offline / On-Prem CSSM
#   Download the license file from CSSM, upload via the UI

# Verify license status via API
$ curl -sk -X GET https://<cml-ip>/api/v0/licensing \
  -H "Authorization: Bearer <token>" | python3 -m json.tool
# Should show: "status": "ACTIVE"

Image Management

CML ships with a set of reference platform images. You must upload your own Cisco images (IOSv, CSR, NX-OS, etc.) separately — they are not bundled due to licensing.

# Navigate to: Tools → Node and Image Definitions
# Upload image files (.qcow2 format)
# Cisco images from CCO are delivered as .bin or .iso — convert with:
$ qemu-img convert -f raw -O qcow2 vios-adventerprisek9-m.SPA.157-3.M8.bin vios.qcow2

# Upload via SCP to CML VM (faster than browser for large files)
$ scp vios.qcow2 sysadmin@cml:/var/lib/libvirt/images/virl-base-images/

# Then in the UI: Node and Image Definitions → Image Definitions → New
# Select the uploaded file and map it to the correct node definition

Recommended Images to Load

PurposeImageFormatNotes
L3 Routing labsIOSv 15.x.qcow2Lightest Cisco router image
L2 Switching labsIOSvL2 15.x.qcow2VLANs, STP, trunking
IOS-XE labsCSR1000v 17.x.qcow23 GB RAM — reserve memory
Data center / NX-OSNX-OSv 9000.qcow2VXLAN, BGP EVPN practice
Firewall labsASAv 9.x.qcow2Multi-context, NAT, VPN
Linux hosts / scriptsUbuntu Server 22.04.imgBuilt-in, no upload needed

External Connectivity

The most common question with CML is: "how do I get my lab nodes to reach the real network (or internet)?"

CML uses an External Connector node — a special bridge object that connects the simulated topology to a physical network interface on the CML VM.

# In the topology canvas:
# 1. Drag an "External Connector" node onto the canvas
# 2. Double-click the External Connector — select the CML NIC to bridge
#    (e.g., ens4 = your second NIC connected to your lab VLAN)
# 3. Connect your topology's uplink router to the External Connector
# 4. Configure the router interface with an IP on your lab subnet

# Example — configure router R1 for external access:
R1(config)# interface GigabitEthernet0/0
R1(config-if)# ip address 192.168.100.10 255.255.255.0
R1(config-if)# no shutdown
R1(config-if)# exit
R1(config)# ip route 0.0.0.0 0.0.0.0 192.168.100.1
# Now R1 can reach your physical network and internet

Your First Topology — YAML

CML supports topology-as-code. Create a lab.yaml file and import it directly — no GUI clicking required.

# lab.yaml — simple 2-router topology
lab:
  title: First Lab
  description: Two IOSv routers, one link
nodes:
  - id: r1
    label: R1
    node_definition: iosv
    x: -200
    y: 0
    configuration: |
      hostname R1
      interface GigabitEthernet0/0
       ip address 10.0.0.1 255.255.255.0
       no shutdown
  - id: r2
    label: R2
    node_definition: iosv
    x: 200
    y: 0
    configuration: |
      hostname R2
      interface GigabitEthernet0/0
       ip address 10.0.0.2 255.255.255.0
       no shutdown
links:
  - id: l1
    i1: r1[GigabitEthernet0/1]
    i2: r2[GigabitEthernet0/1]
# Import via API
$ TOKEN=$(curl -sk -X POST https://cml/api/v0/authenticate \
    -H "Content-Type: application/json" \
    -d '{"username":"admin","password":"yourpassword"}' | tr -d '"')

$ curl -sk -X POST https://cml/api/v0/import \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/yaml" \
    --data-binary @lab.yaml

# Start the lab
$ curl -sk -X PUT "https://cml/api/v0/labs/<lab-id>/start" \
    -H "Authorization: Bearer $TOKEN"

Accessing Node Consoles

# Option 1: Browser console — click the node in the canvas, click "Console"
# Option 2: SSH terminal access via CML console server
$ ssh -p 9000 admin@cml
# Presents a menu of all running labs and nodes
# Select the node — direct console session opens

# Option 3: Direct per-node SSH (after node is configured with SSH)
$ ssh -J admin@cml:9000 cisco@10.0.0.1
# Uses CML as a jump host to reach the simulated node's IP directly

Common Issues and Fixes

SymptomCauseFix
Nodes fail to start — "QEMU error"Nested virtualization not enabledEnable "Expose VMX to guest" in ESXi CPU settings; power off VM first
License shows "NOT CONNECTED"CML VM has no internet accessCheck NIC1 gateway and DNS; or use offline CSSM token
Image not found after uploadFile uploaded to wrong pathSCP to /var/lib/libvirt/images/virl-base-images/ then rescan in UI
External Connector has no trafficBridged NIC not correctVerify NIC mapping; check that CML NIC2 is on the correct VLAN/portgroup
Web UI unreachable after rebootCML services not startedSSH to sysadmin@cml; run: sudo systemctl restart virl2.target
Console hangs at bootInsufficient RAM for node typeCheck node RAM allocation; IOSv needs 512 MB minimum

Quick Reference Checklist

  • [ ] ESXi VM CPU: "Expose hardware-assisted virtualization" enabled
  • [ ] 32 GB+ RAM allocated to CML VM
  • [ ] Storage on SSD/NVMe datastore
  • [ ] NIC 1: management network (reachable from your workstation)
  • [ ] NIC 2: bridge/external network (for External Connector nodes)
  • [ ] Smart Licensing activated — status shows "ACTIVE"
  • [ ] IOSv, IOSvL2 images uploaded and mapped to node definitions
  • [ ] First topology imported via YAML and all nodes booted successfully
  • [ ] Console access tested via browser and SSH jump