Release 0.80#
2026-10-09 · Full Changelog
Breaking changes: CLAB_* environment variables replaced by kind-specific config
Kind-specific node settings are now set as plain YAML keys on the node definition. The CLAB_* environment variables that previously provided these settings are removed and are no longer read, see Kind-specific config for the table of removed environment variables and their replacements.
C9s runtime#
Containerlab can run labs on Kubernetes powered by the all-new open-source project called c9s.
Our end game is to ensure that the containerlab binary can be used both to run host-local labs and know how to spin them on Kubernetes via c9s. The first major stab at this lofy goal comes with this release where we add a new runtime option named simply c9s:
Same deploy, inspect, exec, events, node lifecycle actions, and destroy commands are supported against the c9s runtime. See the Containerlab runtime documentation for more details.
Well, we'd be lying if we said that this is a fully baked runtime. It is not. But it is a good start and we are looking forward to your feedback and contributions.
MACVLAN management networks and Contianerlab IPAM#
The management network can now be created with the macvlan driver, which places node management interfaces directly on the host network. The driver is selected with driver: macvlan and requires a macvlan-parent interface that already exists on the host:
Containerlab ships its own IPAM provider for macvlan networks: addresses are allocated deterministically, saved in the topology state file, and verified with duplicate address detection. For MACVLAN networks, DAD checks local addresses and the ARP/ND cache, then sends an ARP and/or IPv6 neighbour solicitation out the parent interface.
Containerlab also creates an owned macvlan interface in the host namespace by default, so the host keeps access to the management network. Set macvlan-aux: false to disable it; the auxiliary interface is disabled automatically for private, vepa, and passthru modes.
Existing Docker networks with a non-bridge driver can be reused by name — bridge-specific setup is skipped when no Linux bridge is associated with the network.
Multiple management networks#
If the above was not mindblowing enough, how about we tell you you can create multiple management networks (and yes, some can be macvlan) and attach your nodes to them in the same lab? The mgmt section accepts a list of networks. Nodes select their network with the mgmt-net key, which follows the standard node, group, kind, and defaults inheritance order:
name: multi-mgmt-network
mgmt:
- network: net1
ipv4-subnet: 172.31.10.0/24
- network: net2
driver: macvlan
macvlan-parent: eth1
topology:
nodes:
r1:
mgmt-net: net1
r2:
mgmt-net: net2
Multiple management networks are currently supported with the Docker runtime only. Every node must have a mgmt-net defined (or inherited), and the first defined network is the default for tools containers. Nodes using network-mode ignore the mgmt-net key. See multiple management networks.
Tailscale management network#
The management (again!) network can join a Tailscale tailnet. In sidecar mode every node gets a tailscale sidecar container and appears as a device in your tailnet, authenticated with a reusable auth-key:
In proxy mode the whole lab appears as a single device in the tailnet, authenticated via SSO. Individual nodes are exposed by forwarding ports with the /ts port suffix, e.g. 8022:22/ts maps port 8022 of the lab device to SSH of that node.
Kind-specific config#
Kinds that need more than the generic node settings accept their own keys right on the node definition. Kind config keys participate in the regular inheritance model with per-key precedence: node > group > kinds.<kind> > defaults.
topology:
kinds:
cisco_iol:
pid-offset: 64 # previously set with CLAB_IOL_PID_OFFSET env var
nodes:
sros1:
kind: nokia_srsim
config-mode: classic
iol1:
kind: cisco_iol
mgmt-intf: Ethernet1/0
Every key is validated: unknown keys are rejected with an error naming the topology block they were set in, and values are strictly type-checked. The JSON schema models the kind config keys of each kind, so editor autocompletion and validation cover them too. Kind names in the kinds: block are matched case-insensitively.
Breaking changes: CLAB_* environment variables replaced by kind-specific config
Kind-specific node settings are now set as plain YAML keys on the node definition with the new kind-specific config mechanism. The CLAB_* environment variables that previously provided these settings are removed and are no longer read.
Unknown or mistyped keys are rejected at deploy time with an error naming the topology block they were set in, so audit your defaults and groups blocks when they apply to multiple kinds.
| Removed environment variable | Kind config key |
|---|---|
CLAB_IOL_PID_OFFSET |
pid-offset |
CLAB_IOL_MGMT_INTF |
mgmt-intf |
CLAB_IOL_BOOTSTRAP_CONFIG |
bootstrap-config |
| Removed environment variable | Kind config key |
|---|---|
CLAB_SROS_CONFIG_MODE |
config-mode |
CLAB_SROS_DISABLE_COMPONENT_CONFIG |
gen-component-config |
| Removed environment variable | Kind config key |
|---|---|
CLAB_SROS_CONFIG_MODE |
config-mode |
CLAB_SKIP_SROS_SSH_KEY_CONFIG |
inject-ssh-keys |
NOKIA_SROS_SFM |
sfm |
| Removed environment variable | Kind config key |
|---|---|
CLAB_CUSTOM_PROMPT |
custom-prompt |
CLAB_EDA_USE_DEFAULT_GRPC_SERVER |
eda-default-grpc-server |
The components key keeps working for the Nokia kinds and SR Linux, but is now a validated kind-specific config key instead of a generic node field. Per-component VM resources for nokia_sros are set with the typed cpu, ram, and max-nics component keys instead of env entries.
With clab apply, a node whose stored kind config no longer decodes — for example, when a key changed between releases — counts as changed and gets reconciled.
FRRouting kind#
The new frr kind makes FRRouting a first-class citizen in containerlab. Configuration files — frr.conf, daemons, and vtysh.conf — are generated into the node's lab directory and bind-mounted over the container's /etc/frr, so startup-config, enforce-startup-config, and suppress-startup-config behave as they do for other kinds. Which daemons run is selected with extras.frr.daemons; when omitted, every daemon is started.
topology:
nodes:
r1:
kind: frr
image: quay.io/frrouting/frr:containerlab-10.7.1
startup-config: r1.frr.conf
FRR publishes a containerlab image alongside its plain release image, tagged containerlab-<version>. It adds an SSH server with an admin user whose login shell is vtysh, and removes the management network's default routes so they stay out of the lab's routing protocols. clab save writes the running configuration back to the lab directory.
Thanks @mwinter-osr #3382 #3429
SR Linux line card selection#
Modular SR Linux chassis — 7250 IXR-6e, IXR-10e, and IXR-18e — accept several line card flavours, which are now selected with a components block instead of bind-mounting a hand-written topology file:
name: srl_modular
topology:
nodes:
srl1:
kind: nokia_srlinux
type: ixr-10e
components:
- slot: 1
type: imm3-36-800g-osfp
Each of the 13 chassis and line card combinations is validated and also registered as its own type — such as ixr-10e-gen3-osfp — so labs can pin a flavour without a components block. See modular chassis.
Cisco c8000v ZTP mode#
The cisco_c8000v kind supports a third type: ztp. The node boots with no startup configuration and provisions itself over DHCP, which makes it a good fit for zero-touch provisioning labs behind a DHCP/ZTP server. It requires an image tagged ztp-$VERSION, where the install phase is skipped.
A startup-config is rejected on ztp nodes, since IOS XE starts ZTP provisioning only on an empty startup configuration.
Cisco IOL improvements#
IOL nodes with L2 images now receive management IP addressing and SSH bootstrap. Console readiness is detected with stream-based prompt detection instead of a fixed 25-second wait, which cuts the deployment wait down to a few seconds, and the SSH host keys generated in the bootstrap template persist across lab restarts.
Thanks @naoya-oyama #3416
Cumulus VX breakout ports#
cumulus_vx nodes can generate a breakout port layout with the port-count and breakouts kind config keys, producing a ports.conf that renames selected ports to the Cumulus breakout form swpNsM — e.g. port 10 split into four lanes becomes swp10s0 through swp10s3:
topology:
nodes:
leaf:
kind: nvidia_cumulusvx
image: vrnetlab/nvidia_cumulus-vx:5.16.1
port-count: 64
breakouts:
- port: 1..20
channels: 4
- port: 64
channels: 2
This requires an image built with vrnetlab's Cumulus VX breakout support. See breakout ports.
Topology-aware netem#
The tools netem set, show, and reset commands accept --topo/-t or --name, so impairments can be set, inspected, and cleared with topology node names instead of container names. Interface aliases are resolved too, and netem show lists the impairments of all nodes in the topology when --node is omitted.
containerlab tools netem set -n r1 -t netem.clab.yml -i eth1 --delay 5ms
containerlab tools netem show -t netem.clab.yml
SR-SIM netns ownership#
SR-SIM distributed chassis components are attached to an internal namespace pause container — the same way Kubernetes holds pod namespaces — so any component container can be killed and brought back without losing the network namespace. The internal container is hidden from inspect output unless --all is set.
Fortinet FortiProxy#
The new fortinet_fortiproxy kind aliases the fortinet_fortigate kind. For both kinds, the node's license file is now mounted into the vrnetlab container, where a TFTP server serves it to the VM for license activation.
Thanks @KarelChanivecky #3228
network-mode: container: with apply#
apply no longer rejects nodes with network-mode: container:<target>, so sidecars sharing another node's netns can be added or changed on a running lab. When the target node is recreated, dependent nodes are recreated as well, and they wait for their target independently of the --max-workers pool.
Miscellaneous#
- SR Linux interface names are validated when a lab is deployed: only the
ethernet-L/P,ethernet-L/P/C, or shorteL-P,eL-P-Cforms are accepted. A post-deploy panic for restored, runtime-discovered endpoints without topology links is fixed too. #3395 - Bridges added to a running lab are now treated as new nodes on
apply. #3438 - Interface names passed to
vxlan-stitchlinks are sanitized, which fixes SR-SIM deployments with long node or interface names. #3437 inspect --allmerges repeated cells again when--wide/-wis set. #3378- Canonical image names are resolved correctly for registries addressed as
host:port, fixing image pulls and auth lookups for such registries. #3391 - External management access works again for setuid-root installs on iptables-legacy backends, where
iptablesrefused to run with differing real and effective UIDs. #3353 - Fixed a missing client context in the Podman runtime when copying configuration to containers. #3364
- Bind mounts in the Podman runtime carry the
:zoption so files are accessible across security contexts. #3347 sonic-vsmarks its wire interfaces (ethN) ARP-off and IPv6-off so only the port interface answers, preventing stale ARP entries with the wrong MAC. #3390vr-ftosvlink endpoints accept theethernet1/1/X,ethernet 1/1/X, and1/1/Xnames in addition toethX. #3354- The quick setup script installs Docker 29.8.1 on Ubuntu 26.04, uses the official Docker repository for CentOS, checks for an SSH daemon, and relies on the RPM repo config file instead of dnf/yum commands. #3424 #3400 #3431
- Fixed a flaky management interface update when Cisco IOL nodes are redeployed. #3392
- The vrnetlab kinds documentation now mentions the
10.0.0.15management address that transparent management assigns. #3420