ZNetLab

Real labs — the complete guide

Three parts, one server: building labs on it, what it does behind every button, and how to stand one up on Linux, Windows, AWS or Azure.

Part I — for anyone who builds labs. What your account can do, what is on your shelf, and what to do when the device you need is not.
Part II — how the machine works: the image pipeline, the four engines, the icons.
Part III — administrators only: building the server and hosting your images.
Also in the product — these are the tracks of the Guide tab in Real labs (lab/index.html#guide); page and document are generated from the same source, so they cannot disagree.
Generated 2026-10-10

Part I

Building labs

For the account that places and runs machines. Everything here works without ever touching the server itself — and the one thing it cannot do has a section of its own.

1 · What your account can do2 · Your environment3 · What is on your shelf4 · A lab in six clicks5 · Start, and your ceiling6 · Console, capture, save7 · The device I need is missing8 · What you never see

1What your account can do

You can build labs, place machines, cable them, start them, open their consoles, capture traffic and save the result. You cannot put a new image on the server. That is not a limit on your plan — no plan has it. It belongs to the administrator role, because putting a vendor image on a server is a licensing act, not a lab action.

ZNetLab says it in one sentence: Upload images is available to administrators only.
YoursThe administrator’sDraw a topologyPlace and cable machinesStart and stop the labConsole in and configureCapture packets on a linkSave and reopen labsRead the image libraryManage your own accountPut images on the serverCreate and remove accountsSet plans and licencesSee everything running, by anyoneYou never need to cross this line to build a lab.
The whole division. Eight things are yours; the four on the right are owned by whoever holds the image licences.

Your account is on the Free plan. This is what that decides — read out of the same table the server checks:

FeatureWhat it isFree
Built-in devicesVirtual PC, LAN Switch and NAT Cloud — no image or licence neededyes
Vendor imagesAny image the administrator has registeredyes
Packet captureCapture any link and read it layer by layeryes
Export .pcapSave a capture and open it in your own analyseryes
Link conditioningBandwidth, delay, jitter and loss per linkyes
External terminalsConsoles in your own terminal client over telnetyes
Lab snapshotsSave the running configuration of every device at onceyes
Configuration managerExport and import every startup config togetheryes
Send to all consolesType once, apply to every deviceyes
Shared labsHand a lab to a colleague or a classyes
Upload imagesAdd network OS images to the serverno
Manage accountsCreate, disable and remove usersno

2Your environment

Nothing is installed on your machine — no hypervisor, no VirtualBox, no agent. You have a browser. Everything else lives on a Linux server your account was pointed at when you signed in, and you never typed its address: the server reads your plan and issues the machine that licence covers. It is shown, read-only, on the Server tab.

Your browserthis page, nothing elsecanvas · shelf · dockconsole terminalsone socketYour lab space on the serverissued to your account from its planthe machines you placed, runningyour cables, as Linux bridgesyour saved labs and configurationsyours · nobody else sees itreadImage libraryshared, and read-onlythe administratorputs images hereyou read it, you draw from it
Your labs are yours alone. The image library is one shelf everybody draws from and only the administrator adds to.

Your ceilings on Free:

LimitYour plan
Users included1
Image devices per lab2
Saved labs2
Labs running at once1
Frames held per capture2000
Interfaces per device8

3What is on your shelf

The shelf has two parts, and it matters which is which.

DEVICESVirtual PCLAN SwitchNAT CloudCSR 1000vbuilt in · no imagebuilt in · no imagebuilt in · no imageloaded by your adminAlways thereVirtual PC, LAN Switch and NAT Cloud need no imageand no licence. Every plan has them, including free.Addressing, routing, VLANs, DHCP, NAT — all learnable here.Whatever your administrator loadedReal vendor images. You can place and run them —you just cannot add to the row.
If a device is on the shelf, it is yours to use. Nothing on the shelf is withheld from you.

You can open the Images tab and read the whole library — what is installed, which platform it is, which engine runs it. Only the upload area is closed, and it tells you so rather than being hidden.

Upload an imageOnly an administrator can upload images.Said, not hidden — so you know it exists and who to ask.Installed imagesCisco CSR 1000vqemuon the shelfCisco IOSv L2iolon the shelfCisco 3725dynamipson the shelf
The Images tab, as your account sees it. The list is fully readable; the upload card is a sentence.

4A lab in six clicks

This works on any account, on any plan, with no image at all — it uses only the built-ins.

1. open the Lab tab 2. drag Virtual PC onto the canvas — twice 3. drag LAN Switch onto the canvas 4. drag the plug on PC1’s corner onto the switch — pick the cable, press Connect. Again from PC2. straight-through is already chosen for you a click on the plug works too: click it, then click the switch 5. press Start lab seconds — these are namespaces, not machines 6. click PC1 — its console window opens — and type: ip addr add 10.0.0.1/24 dev eth0 ; ip link set eth0 up ping 10.0.0.2 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64

Everything the rest of this guide describes — cabling, starting, consoles, capture, saving — behaves the same whether the device is a built-in or a real router image. The only difference is how long it takes to boot.

Short of time? Press Examples. Those labs are already drawn, and the ones built from built-ins start on any plan.

5Start lab, and your ceiling

Until you press Start, a lab is a document. Nothing exists on the server, and nothing counts against you. Press Start lab and the server checks your plan before it builds anything.

If you are over a ceiling it says so with the numbers, not with a shrug:

Image devices per lab on the Free plan is 2; this lab has 6. Starter allows 4.

Three ways forward, and the first two are usually the right ones: remove a device you are not using, stop another lab that is still running, or move up a plan. A stopped lab keeps everything — the topology and the configurations — so stopping one to start another costs you nothing.

One lab runs at a time, on every plan, and a lab belongs to the window that opened it. Open the canvas in a second tab or a second browser and that one is refused — it will not let you build anything until you close it or carry on in the first window. That is on your side: two windows on one account would both be spending the same allowance, and neither would tell you. A team that needs several labs running together needs an account each.

Booting takes a moment. A built-in is instant; a real router image spends a minute or two at starting before it turns running. If a device goes red, click it — the reason is on the device, and it is usually memory on a shared server rather than anything you did.

6Console, capture, save

Click a running device to open its console. It is the real command line of whatever booted, in a window you can drag, resize, maximise or dock to the bottom edge — and it stays open across every tab, the way a terminal on your desktop does.

A click on a device that is not running only selects it. A terminal onto something that has not booted is a window with nothing in it, and laying out a topology should not leave a stack of them behind. Double-click, or the Console button in the device panel, opens one anyway — which is how you write a startup configuration before anything has started.

Click a link, press Capture, then generate traffic. Frames appear as they cross the wire.
Press Save. The lab moves to My labs, with its configurations.
Pull one device without stopping the lab: the ⏻ on its corner, or Power off in its panel. The cables stay, so it rejoins when you switch it back on.

Click the front panel drawing in a device’s properties to see what the real hardware looks like — where the console port is, how the ports are grouped, and which socket is the interface you are configuring.

Some of what surrounds those three is decided by your plan rather than by the lab. On Free:

ToolYou
Packet captureyes — Capture any link and read it layer by layer
Export .pcapyes — Save a capture and open it in your own analyser
External terminalsyes — Consoles in your own terminal client over telnet
Link conditioningyes — Bandwidth, delay, jitter and loss per link
Lab snapshotsyes — Save the running configuration of every device at once
Configuration manageryes — Export and import every startup config together
Send to all consolesyes — Type once, apply to every device
Shared labsyes — Hand a lab to a colleague or a class

Where something is not included, ZNetLab names the plan that includes it rather than greying a button out and leaving you to guess.

7The device I need is not on the shelf

This is the one thing you genuinely cannot solve yourself, so here is how to solve it in one message instead of three.

First check it is really missing: open Images and read the list. A platform can be installed under a name you did not expect — viosl2 is the IOSv switch, csr1000vng is the CSR.

If it is not there, ask for it from the plan window: your profile, or the Plans page, then See what you can run. It lists every platform ZNetLab recognises that this server has not got, and the form asks for exactly the three things an administrator needs — which platform, which release, and what it is for — so nobody has to come back and ask. Asking carries a small one-time charge for the work of sourcing, checking and filing the image; it is shown before you agree to it, and it is not a charge for the software, which ZNetLab does not supply and cannot license to you.

A message to a human still works, of course. If you send one, send this:

# what to send your administrator Platform Cisco IOSv layer 2 switch Version 15.2, or whatever the course you are following expects Why spanning-tree lab; the LAN Switch built-in does not run STP # and, if you know it, the name ZNetLab expects — it saves them a step viosl2-15.2 platform, then version

While you wait, the lab is rarely blocked outright. The built-in LAN Switch covers VLANs, trunking and access ports; Virtual PC covers addressing, routing, DHCP and NAT through the NAT Cloud. Draw the topology now and swap the real image in when it lands — a saved lab does not care which device type sits at a position until you start it.

8What you never see, and why

Not on your screenWhy
The upload areaPutting a vendor image on a server is a licensing act. It sits with whoever holds the licences, on every plan.
The Admin portal tabAccounts, plans and everything running across the whole server. The tab is not merely disabled — it is not there.
Other people’s labsYour lab space is yours. Sharing is on every plan, and it is opt-in per lab, never automatic.
The server’s address to typeIt is issued to your account from your plan. Being unable to type one is what stops anybody pointing themselves at a machine their licence does not cover.

None of this is hidden from you as a matter of secrecy. Where a thing is out of reach, ZNetLab says which role or plan reaches it — so you always know what you are looking at, and who to ask.

Part II

How Real labs works

What happens behind each button: how an image is identified and filed, how a drawn cable becomes a Linux bridge, which of the four engines boots what, and what every icon means.

1 · The shape of it2 · Sign in3 · Load an image4 · The workspace5 · The icons6 · Build a topology7 · Start lab8 · Console9 · Capture10 · Save11 · Features12 · When it fails13 · Next to GNS3 and EVE-NG

1The shape of it

You draw a topology in this browser. A Linux server boots the actual vendor images and wires them together with kernel networking. The consoles and the packet capture come back here over one WebSocket. Nothing is installed on the machine you are reading this on — no hypervisor, no VirtualBox, no agent. The browser is the whole client.

Your browserthis pagecanvas · shelf · dockconsole terminalsno install · no plugintopologyconsoles · pcapone WebSocketZNetLab serverLinux · your images live hereaccounts · plans · licencesimage importer · librarybridges · veth · namespacesconsole ports 23000–23999namespaceVirtual PC, LAN Switch, NAT cloudIOLL2/L3 IOS as a plain processDynamipsclassic IOS, emulated CPUQEMU + KVMCSR, IOSv, ASAv, vMX, vEOS
Four engines, one server, one socket back to this page. Which engine a device gets is decided by its platform, not by you.

2Sign in — and what the account decides

Real labs is not reachable signed out. One account covers the whole product: the lessons, the free simulator and this lab server.

Enter your email and password. You never type a server address.

The address is a property of the account, not of the browser. When you sign in, the server reads the plan on your account and issues the lab machine that licence buys — a free account lands on the shared machine, a paid one on the machine it pays for. It appears read-only on the Server tab. Change the plan and the account moves with it; there is nothing to retype and no way to point yourself at a machine your licence does not cover.

The same plan sets the ceilings the lab enforces at Start lab — how many devices, how much memory, how many labs may run at once.

3Load an image

Done once, by an administrator. ZNetLab ships no vendor software — you supply images you are licensed to run. Two ways in, and they end in the same place.

Drop folder. Copy the file into <images>/incoming/ on the server. Nothing to click.
Images tab. Sign in as an administrator and drop the file on the upload area. Same pipeline, over the socket.
settle2.5 s quiet · ≥512 KBsniffmagic bytes, not the nameunpackzip · gz · tar · 7zidentify120 platformsconvertqemu-img → qcow2installlibrary/<platform>-<ver>/cannot name it → unidentified/ , kept off the shelf
The import pipeline. Only the identify stage can refuse — and when it does it refuses loudly rather than guessing.
# what actually happens to one file incoming/chr-7.15.3.img.zip → stops growing for 2.5 s a 2 GB copy over the network is safe → first bytes say PK, not QFI the extension was a lie; it is a zip → unpacked chr-7.15.3.img falls out → matched mikrotik 7.15.3 from the image filename → qemu-img convert -O qcow2 raw disks become qcow2 → library/mikrotik-7.15.3/virtioa.qcow2 → on the shelf, draggable

Identity lives in the directory name, not the file name, because a QEMU library image is a folder of disks. That is also why two builds of the same platform never collide: they are two directories, and both stay.

# if it lands in unidentified/, rename it the standard way and drop it again vios-15.6.2T platform, then version csr1000vng-17.03.04a i86bi-linux-l2-adventerprisek9-15.2d.bin IOL keeps its own naming — the build date is not an extension

4The workspace

Open the Lab tab. Four areas, and that is the whole screen.

SelectDeleteStart labStop labConsoleCaptureSaveOpenExamplesDEVICESVirtual PCLAN SwitchCSR 1000vno image · instantno image · 4 portsqemu · 4 GBdrag one onto the canvas →Gi0/1 — Gi0/1power this onedrag to cableR1R2runningrunningLABTwo routersDevices2Links1Running2 / 2Console:230011 · shelf2 · toolbar3 · canvas4 · dock
The Lab tab. Devices on the left, actions along the top, the topology in the middle, and everything about what is selected on the right. The two handles on a device are its power and its cable.
AreaWhat it holds
1 · ShelfEvery device you may place. Three built-ins need no image at all — Virtual PC, LAN Switch, NAT Cloud. Everything an administrator imported appears below them.
2 · ToolbarSelect · Delete, then Start lab · Stop lab, Console · Capture, Save · Open · Examples. There is no Link tool: cabling lives on the device itself, on the plug at its corner.
3 · CanvasThe topology. Drag from the shelf to place; drag the plug at a device’s corner to cable it; the ⏻ on the other corner powers that one device. Click a running device for its console.
4 · DockEverything about what is selected — live state, interfaces and what they are wired to, the startup configuration, and the front panel of the real hardware. With nothing selected, the lab’s own counts.

5The icons, and what each one means

A device is drawn by its kind, not its brand — a Cisco router and a Juniper router share a drawing because on a diagram they do the same job. The registry maps each platform to one of these, and a few platforms are named exactly where the generic drawing would tell you nothing (a wireless controller is not a router).

RouterRoutes between networks
Layer 3 switchSwitches and routes
SwitchOne LAN, many ports
HubRepeats to everyone
FirewallDecides what may pass
IPSInspects and blocks
VPN gatewayTunnel endpoint
Load balancerSpreads sessions
PCA host that pings
LaptopClient machine
ServerRuns a service
StorageDisk or array
VoiceCall manager, phone
WLAN controllerManages the APs
Access pointWireless
CloudSomebody else’s network
NAT cloudThe way out to the internet
WAN linkDelay, jitter, loss
Traffic generatorOstinato and friends
AnalyserWatches the traffic
UnrecognisedRegistered, but unnamed

And what the real one looks like

An icon says what a device does. It says nothing about what you would be standing in front of with a console cable in your hand — which is the other half of learning this, and the half a simulator usually skips.

So every device also has a front panel in its properties: the chassis, the ports laid out the way that family lays them out, the console port picked out in its own colour, the status LEDs — and each socket carrying the same interface name you are typing into the CLI. That last part is the point. Gi0/1 stops being a string in a configuration and becomes the second port from the left. Click the drawing to open it at a size where the labels can be read.

FamilyWhat its panel teaches
RouterOnboard interfaces versus the ones on cards — which is what the middle number in Gi0/1/0 counts — plus console, aux and the slots themselves.
SwitchPorts grouped in fours the way the metal groups them, SFP uplinks at the end, and the MODE button that changes what the port LEDs mean.
Firewall and appliancesA row of identical ports, and a separate management port — because which interface is inside and which is outside is a decision you make, not something the box knows.
ServerDrive bays on the front, network at the back, two NICs on purpose, and an out-of-band port that works when the operating system does not.
HostOne port, one address, one default gateway — and the link light no amount of configuration will fix.
These are drawings of a family, not photographs of a model. A Catalyst 2960 and an EX2200 are not the same box and nothing here pretends they are. What is accurate is the shape of the class — how many ports, in what grouping, where the console lives — and the interface labels, which are your device’s own. A cloud gets no panel at all, because a cloud is not a box.

The label under a device carries its state, and links are coloured the same way:

ColourDeviceLink
greyPlaced, not startedDrawn, not built yet
amberStarting — a real router takes a minute or twoCable up, protocol down
greenRunning; the console will openUp, and carrying traffic
redDid not start; click it for the reasonBroken or removed underneath

6Build a topology

Drag two devices from the shelf onto the canvas.
Point at one of them and drag the plug on its corner onto the other. Rather not drag? Click the plug instead and then click the far device — same result, and Escape or a click on empty space puts it down.

Either way you are asked two things: which cable, and which interface at each end. Seven media are offered — straight-through, cross-over, fibre, serial, console, coax and wireless — and the one that fits the two devices is already selected, so the usual answer is to press Connect. The interfaces that suit the cable are listed first; ones already carrying a link are shown as in use rather than hidden. If neither device has the kind of interface the cable wants — a serial or a radio — the picker offers to add one, named the way the platform names it.

The medium is a property of the drawing: on the canvas a serial WAN link, a fibre uplink and a wireless association each look like themselves, and a key in the bottom-left corner names the ones this lab uses — only those, so a diagram with one kind of cable does not get a seven-row legend. Underneath, all of them are the same Linux bridge. Change it later from the link’s panel — no restart, because nothing about the datapath changed.

Nothing has been created on the server yet. Until you press Start, a lab is a document — devices, positions, links and the ports they land on. That is deliberate: you can draw the whole thing offline, save it, and start it later, or on another server.

In a hurry, press Examples and open Two PCs on a wire. It is already built and it starts on any plan, because it uses only built-ins.

7Start lab — what the server actually does

This is the moment the document becomes running software. Seconds for built-ins; a minute or two for a real router image.

1. check the plan devices, memory and running labs against your licence 2. build the links one Linux bridge per link ip link add br-l1 type bridge ; ip link set br-l1 up 3. build the devices a namespace and a veth pair per interface ip netns add r1 ip link add r1-eth0 type veth peer name br-l1-p0 ip link set r1-eth0 netns r1 ; ip link set br-l1-p0 master br-l1 up 4. start the engine chosen from the platform, not from you 5. bind a console one TCP port each, from 23000 6. icons turn green, consoles open
one line you drew → what exists on the serverR1netns r1r1-eth0Linux bridgebr-l1this is the wireR2netns r2r2-eth0veth pairveth pairReal frames cross this. That is why the capture is a real .pcap.
A link is not a metaphor. It is a bridge in the kernel with a real interface on each side.
EngineRunsWhat it costs
NamespaceVirtual PC, LAN Switch, NAT CloudKilobytes. Starts instantly — it is kernel networking, not a machine.
ContainerFRRouting, Nokia SR Linux, Arista cEOS, any Linux imageTens of megabytes, up in a second or two. No emulated CPU and no virtual machine, so it does not care whether the host has hardware virtualisation. ZNetLab gives the container its interfaces from the topology, so it forwards like anything else on the canvas.
IOLL2/L3 IOS as a native Linux processTens of megabytes. Needs a NETMAP for the wiring and an iourc licence file — beside the image, or once at the top of the library for all of them.
DynamipsClassic IOS — 3725, 7200 and friendsA software CPU, so it is the slow one. Slots and cards are planned for you.
QEMU + KVMFull disk images — CSR, IOSv, ASAv, vMX, vEOSReal RAM, the amount the platform asks for. Uses /dev/kvm, already in the kernel.

One device at a time

Start lab boots everything. Afterwards each device has its own power — the ⏻ on its top-left corner, or Power on / Power off in its panel.

That is not a convenience, it is the experiment. Pull one router and watch the protocol reconverge; put it back and watch it settle. Stopping the whole lab to do that would take every other console and every running capture down with it. The links stay in place while a device is off, so it rejoins the topology it left.

This is why there is no hypervisor to install. Three of the four engines are not virtual machines at all. Only full disk images need virtualization, and they use KVM — which is part of Linux. A modest server therefore runs far more devices than one-VM-per-router ever could.

8Console

Click a running device. Its console opens in a window — drag it by the title bar, resize it from the corner, maximise it, or dock it to the bottom edge. Every device you open gets a tab, and the window stays put while you go and look at another tab.

Clicking a device that has not booted only selects it, and moving one opens nothing — so laying out a topology does not bury the screen in terminals. To write a configuration before anything is running, double-click instead, or press Console in the device panel: what you type there is kept and pasted in the moment the device boots.

Prefer your own terminal client? Set it as your default console from the ⚙ in the window’s title bar, and a click on a device opens the device there instead — or in both at once. Section 8 explains how that works and what it cannot do.

Output is coloured as it arrives, keyword by keyword: an interface going up or down, a rejected command, a ping that answered or did not, interface names, addresses and the IOS facility on a log message each read differently. A console scrolls faster than anyone reads, and the point is to make what you are watching for findable without reading every line. Real ANSI colour from the device is honoured too, rather than printed as escape codes.

Log gives you the transcript: save it to a file, copy the lot, or turn on a timestamp against every line. The file is written in the usual session-log shape — opened and closed lines around the session, and no escape codes in it.

It is the vendor’s own command line, because it is the vendor’s own software booted from your image. Nothing is reimplemented. Every device also gets a TCP port in the 23000–23999 range, so your own terminal can attach to the same console at the same time — useful when two people are looking at one problem.

If you would rather use your own terminal

You can make that the default. The ⚙ in the console window’s title bar — and the Default console card on the Server tab — set what a click on a device does:

ChoiceWhat happens
In this windowZNetLab’s own console. The default.
In my telnet clientZNetLab hands the address to telnet:// and your registered client opens the device.
In bothBoth windows, on one session — what you type in either is seen in both.
Worth being plain about the mechanism. A web page cannot start a program on your machine, and nothing here pretends otherwise. What it can do is hand the operating system a telnet:// address; whichever client is registered for that answers. Register your terminal client as the telnet handler once and every device opens there. Nothing registered? ZNetLab gives you the exact command line to paste, for the client you named — and clicking that message copies it.
# the command ZNetLab shows, for whichever client you chose SecureCRT securecrt /T /N "R1" /TELNET 10.0.0.14 23001 PuTTY putty -telnet 10.0.0.14 23001 telnet telnet 10.0.0.14 23001

The setting belongs to the browser, not the account — a client is wanted on the machine it is installed on. External terminals are a plan feature; where yours does not include them, the click still opens the console in the page and says why.

The window itself behaves the way a terminal does anywhere else, because it is one: every key goes to the device as you press it and the device echoes, exactly as in any terminal. So history on the arrow keys is the device’s own history, Tab and ? are answered by the device, a password prompt hides what you type, --More-- pages on a space, Ctrl-C really does break a running ping, and Ctrl-Shift-6 sends the Cisco break. Ctrl-Shift-C/V for copy and paste (plain Ctrl-C has to stay break), Shift-PgUp/PgDn to scroll, Ctrl-Shift-F to search the scrollback, and A− / A+ for the text size. Scroll up and it stops following, so output cannot yank the view away while you are reading — the status bar says scroll lock while that is true, alongside the connection, the console address, the measured size, how long the session has been open and how much scrollback is behind you.

ColourWhat it marks
R1(config)#The prompt
greenup, !!!!!, Success, established, permit
reddown, denied, err-disabled, timeouts — and a rejected command in a brighter red
purpleThe IOS facility on a log line — %LINK-3-UPDOWN:
cyanInterface names, long or short
blueAddresses and masks
greyDevice timestamps and MAC addresses

It is deliberately conservative. Colour that is wrong is worse than colour that is absent, because it teaches you to distrust all of it. Where the device sends real ANSI colour of its own, that wins — nothing is repainted over it.

Log opens a small menu: Save session log writes a file named for the device and the minute, Copy everything puts the transcript on the clipboard, and Timestamp every line prefixes each line with the time it actually arrived — captured when it was written, not invented at save time. The file carries the usual opened and closed session-log lines, and no escape codes.

--- Session log opened at 2026-08-30 14:02:11 - R1 - 10.0.0.14:23001 --- [2026-08-30 14:02:19] R1# ping 10.1.1.2 [2026-08-30 14:02:21] !!!!! Success rate is 100 percent (5/5) --- Session log closed at 2026-08-30 14:06:40 ---
R1 · console R1> enable R1# configure terminal R1(config)# interface GigabitEthernet0/1 R1(config-if)# ip address 10.1.1.1 255.255.255.0 R1(config-if)# no shutdown R1(config-if)# end R1# ping 10.1.1.2 !!!!! Success rate is 100 percent (5/5)

9Capture

Click the link, press Capture, then generate traffic.

Writing and drawing on the diagram

A topology is a drawing somebody else has to read, and a cable is only half of what it says. Draw ▾ in the toolbar adds the other half: a note for text, a rectangle or ellipse to box a group — drawn behind the devices, so what you drew around is still visible and still clickable — and a line for a boundary of your own.

Ctrl+A selects every device, a box dragged on empty canvas selects what it covers, and shift-click adds one. They move together and delete together, and deleting asks first. Escape stops drawing and lets a selection go. All of it is saved with the lab and travels with it to the portal; none of it is a device.

Slots and cards

A real 7200 has no FastEthernet1/0 until somebody puts a PA-2FE-TX in slot 1. ZNetLab fits the cards for you by default, but the card decides what the port is — an NM-4T makes Serial1/0..1/3 where an NM-1FE-TX makes FastEthernet1/0. Select a device with card slots and the panel lists them; choose a card and the interfaces are rebuilt from it.

Slot 0 is onboard on the integrated routers and cannot be changed — the emulator fits it itself and aborts if asked for it twice. An empty slot stays empty. A slot will not change while a cable is attached to a port it would remove, and a running device keeps its hardware until it next starts.

Two ways in, and they are the same capture. Click a link and press Capture to watch that cable; click a device and press Capture to watch that machine — with one cable it starts at once, with several it asks which interface and names what is on the far end. An interface is a link, so nothing is recorded twice.

Protocols answers the three questions a capture usually gets asked. Which packets should be here — read out of the startup configuration of the two devices on this cable, so an OSPF that is configured and silent is a red row rather than a mystery. Are they on time — the measured interval beside the protocol’s own default, and beside the interval the packets themselves advertise, because OSPF, HSRP, STP and BGP all carry their timers in the frame. If the two ends advertise different timers the adjacency will never form, and nothing else in any product tells you that. And which ones cause trouble — an ARP nobody answered, two devices claiming one address, an unreachable, a reset, a Discover with no Offer, a broadcast storm, and the IOS Ethernet keepalive that flaps every emulated link. There is a table of every default timer at the bottom, worth reading before you capture anything.

The pane opens on Overview: the rate, the protocol mix, who is talking and the conversations, as figures rather than tables — and every bar is a filter, so clicking one takes you to the packet list with that protocol or that address already applied. Packets is the list with the layer-by-layer detail and the bytes; Flow is the time-ordered graph of who sent what to whom.

Open externally pipes the live stream into your own analyser. The server is already running tcpdump; this hands you those bytes untouched, so it is treated as a live interface instead of a file that stopped being true when you saved it. The command is written for you, with the address, the capture id and your session token in it — which is why it must not be pasted into a ticket. A capture belongs to whoever started it; nobody else can read that stream, administrators included.

Pick a cable in that window and the capture is started for you, and what you get back is an address your analyser can open on its own — no token to paste and no curl to get right, because the key is in the address. There is also a launcher to download: a small script you double-click, which opens your analyser on the live stream. The key opens that one capture and nothing else, it is yours, and it stops working after fifteen minutes or when the capture stops.

Frames appear as they cross the bridge, and Export .pcap hands you a file any analyser opens. These are real frames off a real interface, not a rendering of what the traffic ought to look like — which is the whole difference between a lab and a simulator.

A link also takes conditioning: add delay, jitter or loss to a cable and watch what the protocol does about it.

Live, next to Capture on the toolbar, draws every captured frame on the cable it crossed — a coloured marker travelling from the device that sent it to the one that received it, with a running count above each device. Hover a packet to hold it still and click it to open that frame in the analyser, with its layers and its bytes. Each device’s own panel grows a Live traffic list of the last frames in and out of its interfaces, and every row opens the frame too. It draws what a capture reads and nothing else: switch it on with nothing being captured and it offers to capture the cables for you.

Each cable also keeps what last crossed it on a small label under the wire, so a cable says what is on it even when you were not watching for the marker. Right-click the Live button for two settings: the addresses on each packet, and slow motion — which is what to use when a short cable makes a packet a flicker.

Which way a packet was going is not in a capture — tcpdump on a bridge reports the frame and not the port it came in on — so ZNetLab reads the bridge’s own address table instead of guessing. Until that answer arrives a marker is drawn hollow and says so.

Everything the workspace tells you is kept. The Notifications tab in the bottom-right corner carries a count and the colour of the worst thing in it you have not read; click it for every notice with the time it arrived, filtered by kind if you want. Which ones also appear as a card over the drawing is a setting in that list — errors only, by default. Nothing is lost and nothing sits on top of your topology.

Operations · NOC, under the toolbar’s tools menu and in your account menu, is the other half of watching a lab. Give each device a Site in its panel — HQ, Branch-2, DC-East — and that screen groups them into places and says which place is down, which is short of devices, and what raised every alarm, with what to do about it. It also reads each device’s TACACS+ and RADIUS configuration: which server it points at, whether a shared key is set, whether that server is a device in this lab and whether it is running — and, when a capture is going, whether those frames are really crossing the wire.

10Save, stop, come back

Press Save. The lab appears under My labs.

A saved lab keeps the devices, their positions, the links and the configurations you wrote. Stopping a lab frees the server’s memory without losing any of that, so tomorrow you press Open and then Start, and it comes back as you left it.

11What Real labs gives you

Real vendor softwareCisco, Juniper, Arista and the rest, booted from your own images. Every command is theirs.
120 platforms recognisedFrom their image filenames, so an existing image library works unchanged.
Three devices with no imageVirtual PC, LAN Switch and NAT Cloud work before you own a single licence.
Consoles two waysIn this page, and on a telnet port for your own terminal at the same time.
A console that reads like oneColour coding, find in scrollback, a status line, and a session log with timestamps.
Your own client, if you preferMake your own terminal the default, and a click on a device opens it there.
Power one devicePull a router, watch the protocol reconverge, put it back — without stopping the lab.
The real front panelEvery device drawn as the hardware, with your own interface names on the sockets.
Real packet captureOff the bridge, exported as a .pcap any analyser reads.
Live packet trackingEvery captured frame drawn on the cable it crossed. Click one to open it.
Protocols, checkedWhich should be on this cable, whether their timers match, and the faults that cause the trouble.
Your own analyserA cable’s live stream at an address it opens by itself, or a launcher you double-click.
Operations · NOCDevices grouped into sites, every alarm with what to do about it, and the TACACS+ and RADIUS each device points at.
Link conditioningDelay, jitter and loss on any cable.
Saved labsTopology and configuration survive a stop.
Plan-aware limitsEnforced on the server at Start, with the numbers named rather than a bare refusal.
AccountsEvery account on the server, managed like a directory — and drawn as a picture in the portal.
Admin portalImages, what is running, and a record of who did what.
# the whole flow, on one line admin drops an image → ZNetLab identifies and files it → it appears on the shelf → you drag it on → you draw a cable → Start lab → server builds bridges, namespaces and processes → icons turn green → console → configure → capture → save

12When something does not work

What you seeWhere to look
The image never reaches the shelfIt is in unidentified/. Rename it the way section 3 shows and drop it again.
Start refusesA plan ceiling. The message names the number — devices, memory, or labs already running.
A device goes redClick it. The engine’s own error is on the device, not buried in a log.
The header says not connectedThe Server tab: it shows the address your licence issued and what the server last reported.
A link stays amberThe cable is built; the protocol is not up. That is a configuration answer, and it is the point of the lab.

13Next to GNS3 and EVE-NG

All three boot the same images the same way: one qemu-system-x86_64 per device, with a per-device copy-on-write disk in front of a read-only library file. They differ in three places, and only three: where the knowledge of which flags an image needs is kept, how the console is carried back to you, and how the cables are made. Everything that looks like a deep architectural difference comes out of one of those.

Three paths to the same QEMU processWhat each product decides, from the file on disk down to the cableGNS3EVE-NGZNetLabImage fileRecipeDevice diskAccelerationConsoleCableAny filenamehda.qcow2 in a folderAny filenameA .gns3a appliance fileA template per productA platform tableLinked clone, made withA working copy underAn overlay per deviceaccel=kvm or accel=tcg,accel=kvm, hard-coded-enable-kvm, else TCG,QEMU serves it itself:-serial mon:stdio;A UDP tunnel betweenA tap in a Linux bridgeA tap in a Linux bridge-serial mon:stdio;serial only, no screenpicked in the GUInamed for the templatea regex recognises it228 here, 1,115 versionsone qemu_options string352 known, 124 its ownqemu-img backing_file/opt/unetlab/tmpunder work/devicesfrom a settinginto the templatedecided at every starttelnet, VNC or SPICEtelnet or VNCthe QEMU processes
Read down a column for one product. Five of the six rows are the same decision taken three ways and none of them stops an image booting. The marked row is the one that does.

Where the knowledge of how to run an image lives

None of the three works it out by looking at the file. Each keeps a written description per product, and the three formats hold almost the same fields under different names. GNS3 keeps a .gns3a appliance file per product, written by the vendor or the community. EVE-NG keeps a template per product under /opt/unetlab/html/templates/, where the whole QEMU incantation is one qemu_options string, and pays for that simplicity with a naming rule: the image must sit in a folder named for the template and be called hda.qcow2 or virtioa.qcow2. ZNetLab keeps a platform table that both the server and this page read, with a pattern per platform that recognises an image by its filename.

On this server there are 228 appliance files describing 1,115 versions between them, and 352 platforms in the table, 124 of them ZNetLab own (109 QEMU, 6 Dynamips, 2 IOL, 4 Docker and 3 built-ins that need no image). A built-in is never replaced by an imported file, which is why 27 appliance files are read at every start, found to clash, and set aside.

What a version can nameHow many of the 1,115 do
a main disk1,090
a second disk330
a CD-ROM179
a BIOS or firmware file31
a kernel and an initrd4 and 2

All of those are carried through to the command line here, along with the boot priority, the guest architecture and the appliance own extra QEMU arguments. Every disk interface the 228 files ask for is built: virtio (107), ide (92), sata (14) and scsi (10).

Why an image that boots can still look dead

A QEMU guest talks either down a serial line or onto a screen, and which one it uses is a property of the image, not a preference. The appliance files say so, and on this server they say it like this:

The console the appliance asks forHow many of the 228
telnet — a serial line129
vnc — a graphical screen64
spice — a graphical screen5
http — a web page inside the device3
not stated27

All three read that field and act on it. A serial appliance gets a terminal; a graphical one gets a screen. That is new here, and it is worth saying what it replaced: ZNetLab used to read vnc, write down no console, and start the machine with a serial line it would never write a byte to. 69 of the 228 appliances are of that kind — Cisco ASAv, ISE, vWLC, DCNM, Aruba VMC, Kali, FreeBSD, CentOS and every Windows desktop — and each of them booted perfectly, held its memory, answered on the network, and looked from the only window you had on it exactly like an image that did not boot.

What happens instead now: a device whose platform says its console is a screen is started with QEMU’s own VNC server on the loopback rather than -nographic, and its console window gains a Screen button beside the terminal. The picture comes over a WebSocket this server authenticates with a one-use ticket that dies in thirty seconds — so nothing about the screen is reachable from outside the host, and no credential is ever written into a URL. Keyboard and mouse go back the same way, and Ctrl+Alt+Delete has a button of its own because no browser will hand that chord over.

Beside the terminal, not instead of it. A Linux guest writes its boot to the serial line and paints a screen, and the serial side is what the cloud-init password, the boot watcher and the measured boot times are all read from. One button switches between the two faces of the same window.

Hardware acceleration, and what it really decides

KVM is not a feature any of the three implements. It is a kernel interface onto the processor own virtualisation instructions; with it QEMU hands guest code to the CPU to run directly, and without it QEMU translates every guest instruction, which is roughly ten times slower and otherwise the same machine. A server that is itself a virtual machine, on a host that does not pass virtualisation through, cannot have it — and nothing inside the guest can change that. GNS3 or EVE-NG installed on such a host hits the identical wall; neither avoids KVM, they are simply normally run on a machine that has it.

Of the 228 appliance files, 116 say they require it, 62 say they allow it, 48 say nothing and 2 say to disable it. Require is mostly a wish, though, not a fact: it usually means or it will be slow. Alpine Cloud Guest says require and boots on a host with no KVM in about four minutes. There are exactly two ways a guest genuinely fails without it, and they look identical from the lab — an open console with nothing in it:

What goes wrongWhat it looks likeWhat answers it
The loader never finishesThe BIOS hands over and nothing further happens. Measured on a Nexus 9000v: fifteen minutes, not one byte on the console, 69 MB of 8,192 ever touched.Nothing, on this host. ZNetLab refuses such a platform before it allocates memory, a tap, a console port or a disk, and says why.
The guest idles on HLT and the clock stops with itThe kernel loads, prints its last line, and the QEMU process drops to 0% CPU and stays there. Measured on the classic Cisco ASA.-icount auto, which the platform now carries. The same image reaches its banner in about two minutes.

What this server does that the other two do not

It resumes a booted machine instead of booting it again. Once a device has reached a prompt, ZNetLab tells QEMU to write the whole machine — memory and devices — to a file, and the next start of a machine of that exact shape loads it and comes up already booted. The file is keyed by everything that would make it the wrong state to load: image, RAM, CPUs, NIC model, port count and accelerator. Neither GNS3 nor EVE-NG has anything of the kind; both boot the guest every time.

It refuses with a reason, before it spends anything, where the other two leave you with a QEMU error or a setting that says no. It measures this host rather than guessing, so the countdown on a booting device is this machine own figure for that platform. It reads the console and names what it sees — three line-protocol drops inside two minutes is the Ethernet keepalive failing on a bridged interface, and it says so once per device rather than leaving somebody to work out why pings are dropping. And an image becomes a device by being dropped in a directory: no folder to name, no appliance to pick first.

What is missing here, in the order it costs you

This list is not an opinion. It is what the appliance importer writes down, per file, when it reads something it cannot honour:

What it cannot doAppliances affected
Draw a SPICE console as SPICE rather than as VNC5
Give individual ports their own NIC model10
Supply a Dynamips idle-PC the appliance does not name9
Proxy a console that is a web page inside the device3
Mount volumes inside a container2
Fit WIC cards named by a Dynamips appliance1
Apply a CPU-throttling setting1

The line that used to head this table — draw a graphical console, 69 appliances, 30% of the library — is gone from it, because it is built. What is left is small: a SPICE appliance is run with a VNC screen instead, which shows the machine but carries neither the shared clipboard nor the USB redirection SPICE would have. Thirty appliances also try to pass -nographic and fifteen -smp; those are dropped on purpose, because ZNetLab sets them itself and QEMU takes the last of a repeated flag.

What would change it, in the order it pays

Two problems, and they pull in opposite directions: a host with no hardware assist translates every instruction, so running machines are expensive; and a third of the library cannot be looked at. Seven things would move both, and they are listed by what they return rather than by how interesting they are. None of them needs hardware this server does not already have, except the last.

What to buildWhat it doesWhat it buys
1 · A screen in the browser — builtA graphical appliance is started with QEMU’s own VNC server on the loopback, and the picture is carried to a canvas in the console window over a ticketed WebSocket. One button switches between the screen and the serial line; Ctrl+Alt+Delete, a redraw and a screenshot sit beside it.69 appliances stopped looking dead, including every GUI Linux desktop, the ASAv, ISE, vWLC and the rest — 30% of the library, and it needed no KVM.
2 · Notice the halted guestA QEMU process that has printed its kernel banner and then sits at about 0% CPU with nothing more on its console has the ASA disease: it idled on HLT and the virtual clock stopped with it. The server can read that from the process itself, say so on the console, and offer to start it again with -icount auto.Turns the commonest silent failure into a named one with a button. It generalises the fix the ASA already carries to every image with the same disease, instead of waiting for somebody to find each one by hand.
3 · A queue for startingThe load is the boot, not the running: a booted guest that is idle costs almost nothing, while a booting one translates its whole startup. Start at most a few devices at a time and let the rest wait, with the canvas saying so.Flattens the spike that eight devices started together make, and usually finishes the whole lab sooner, because TCG threads stop fighting each other for the same cores.
4 · Warm start, used harderAlready built, and the single largest saving on a host like this: the state of a booted machine is written once and loaded on the next start, so the boot — the expensive part — does not happen twice. Worth keeping states for more shapes and discarding them less eagerly.A device that resumes skips the whole of what TCG is slow at. It is the difference between minutes and seconds, per device, every time after the first.
5 · Honour the throttle the appliance asks forTen appliance files name a process priority and one a CPU throttle, and both are read and ignored today. Running QEMU at a lower priority, and capping the greedy ones, is a few lines where the process is spawned.Stops one badly behaved guest making every other device on the server feel broken. It does not make anything faster; it makes the slowness fair.
6 · Turn on page mergingTen Linux guests from one image hold ten copies of the same kernel and libraries. The kernel can merge identical pages between them, and it is switched off on this host.Memory, not CPU — but memory is what decides how many devices fit, and the saving across guests of one family is large.
7 · A second lab server, where KVM existsThe only answer to an image that genuinely cannot boot without hardware assist. ZNetLab is already client and server, with the address issued to an account rather than typed, so a second machine with nested virtualisation enabled can carry the handful of platforms that need it.The last gap closes. Everything else on this list works on the host you have.

The first is done. The second changes what a reader sees the next time an image hangs; the next four change what the server feels like under a full lab; and only the seventh needs somebody to buy a machine.

Cisco, IOS, Catalyst, Meraki, Packet Tracer, CCNA, CCNP, CCIE, Juniper, Junos, Arista, EVE-NG, GNS3, Wireshark, SecureCRT, PuTTY and other names are trademarks of their respective owners. ZNetLab is an independent product and is not affiliated with or endorsed by them. ZNetLab ships no vendor software. Terms · Privacy · Licences

Part III

Standing up a server

Administrator work. One Linux machine holds the images, boots them and answers a socket — here is how to build it on each of the five platforms, and how to get your images onto it.

1 · What you are building2 · What the machine needs3 · Install it4 · First sign-in5 · Host your images6 · Prove it works7 · Keep it running8 · Lock it down

1What you are building

One Linux machine. It holds the images, boots them, wires them together with kernel networking, and answers a WebSocket. Everybody else needs only a browser — there is no client to install, roll out, or keep in step.

Everybody elsea browsernothing installednothing to roll outws://server:8080The one server you buildNode — the ZNetLab process, port 8080accounts, plans, the activity trailthe image library and the importerDynamips · IOL · QEMU/KVM · namespacesbridges and veth pairs — the cablingruns as root: bridges and namespaces need itThree directoriesimages/incomingyou drop files hereimages/libraryZNetLab files them here/var/lib/znetlabaccounts and labs — mode 700Back up the third one.Images can be copied again.Accounts and saved labs cannot.
One machine, three directories, and a browser at the other end.

2What the machine needs

ThingMinimumWhy
LinuxUbuntu 22.04+ / Debian 12 / RHEL 9Namespaces, veth and bridges are the cabling. Nothing else has them.
RootrequiredBridges, tap devices and namespaces are root-only. This is not avoidable.
Node.js16+The server itself. deploy.sh installs 20 if yours is older.
RAM8 GB, and more per userRoughly 512 MB per IOSv node and 4 GB per CSR or Nexus. Namespaces cost kilobytes.
Disk100 GB+Images are 1–4 GB each and you will keep several versions.
/dev/net/tunrequiredWithout it QEMU nodes cannot be wired at all.
/dev/kvmstrongly wantedWithout it QEMU images still run — about ten times slower. Dynamips, IOL and the built-ins do not care.

That last row is the only thing that really differs between the platforms, so here it is in one place:

does this platform give you /dev/kvm?Linuxyeson real hardwarethe best caseWindows · WSL2yesnested virtualizationgood for one laptopVMware · your PCyestick Virtualize VT-xfull-speed QEMUAWS · EC2only .metalNitro gives no nestingpick bare metalAzure · VMyesv3 sizes and newerno bare metal needed
The one architectural difference between them. Everything after this is the same server.

3Install it

Pick where it is going. The steps change; what you end up with does not.

Linux — Ubuntu, Debian or RHEL

A clean Ubuntu or Debian box to a running lab server in one command. The script installs the packages, makes the directories, asks for the administrator password, starts the service — and then proves the result rather than announcing it.

# on the server, as root git clone <your znetlab checkout> or copy the folder across cd znetlab/server sudo ./deploy.sh # the defaults, if you want to change them sudo ./deploy.sh --port 8080 --images /opt/znetlab/images --work /var/lib/znetlab

What it does, in the order it does it:

StepWhat it means
Packagesiproute2 bridge-utils tcpdump iptables qemu-kvm qemu-utils dynamips unzip xz-utils — installed one at a time on purpose, so one missing from your mirror does not stop the rest.
Node.js16 or newer. It installs Node 20 from NodeSource if yours is older or absent.
KernelLoads bridge, veth and tun, checks /dev/net/tun and /dev/kvm, and turns off bridge-nf-call-iptables — bridged frames walking the firewall is a cost for nothing and a way for packets to vanish invisibly.
Directoriesimages/{incoming,library,unidentified} at 755, and /var/lib/znetlab at 700 — accounts and the activity trail live there.
AdministratorAsks for a password, twice, not echoed, 8 characters minimum. If accounts already exist it leaves them alone.
ServiceWrites znetlab.service for systemd. It runs as root because bridges, taps and namespaces cannot be made without it.
Verifyverify.sh checks the kernel before starting anything, then verify-lab.js drives the running server and checks the kernel agrees with it.
If the kernel checks fail, the script stops instead of starting a server that would build labs which quietly do not forward traffic.
# run at boot, and watch it systemctl enable --now znetlab journalctl -u znetlab -f # or just the log tail -f /var/log/znetlab.log

Windows — through WSL2

ZNetLab needs Linux networking — namespaces, veth pairs, bridges. Windows does not have those, so on Windows the server runs inside WSL2, which is a real Linux kernel. You do not have to learn WSL: one script does the whole thing.

# 1. install WSL, in an ADMIN PowerShell — then RESTART Windows wsl --install # the restart is not optional: it is what starts the Hyper-V compute service. # without it the next step fails with HCS_E_SERVICE_NOT_AVAILABLE.
# 2. after the restart, in a NORMAL PowerShell window cd znetlab\server .\deploy-wsl.ps1 # options .\deploy-wsl.ps1 -Distro znetlab -Port 8080

It registers the distribution, installs the packages inside it, verifies the Linux datapath, starts the server, proves it with a real lab, and prints the address, the username admin and a generated password — copy that password before you close the window.

One thing to know about WSL2. There is no systemd, so it will not start on its own after a reboot — run the script again, or start it by hand. And Dynamips is not installed by the WSL script, so classic-IOS images are the one engine you add yourself if you need it.

Two Windows-only conveniences worth knowing:

WhatWhere
The drop folder, in ExplorerPaste \\wsl$\znetlab\opt\znetlab\images\incoming into the address bar and drag images in like any folder.
The logwsl -d znetlab -u root -- tail -f /var/log/znetlab.log
Stop itwsl -d znetlab -u root -- pkill -f server.js

KVM works: WSL2 supports nested virtualization, so QEMU images run at full speed. This is a genuinely good way to run a personal lab server on a laptop.

VMware — Workstation or Player

Every other platform on this list either has hardware virtualisation or does not. This one hands it out: a desktop with VT-x or AMD-V can pass that through to a Linux virtual machine, which is exactly what a rented VPS usually refuses to do. So if the QEMU images are the point — IOSv, CSR1000v, ASAv, vSRX — a Linux VM on a machine you own beats a cloud instance that bills you for software emulation.

One checkbox is the whole platform. VM settings → Processors → Virtualize Intel VT-x/EPT or AMD-V/RVI. It is off by default. Without it the guest has no /dev/kvm, QEMU translates every instruction, and you have rebuilt the slow VPS on your own hardware. If your edition does not show the box, the line vhv.enable = "TRUE" in the .vmx file does the same job; on ESXi the wording is Expose hardware assisted virtualization to the guest OS.
# 1. the VM: Ubuntu 22.04 or 24.04, 4 vCPUs, 8 GB RAM, 100 GB disk # Processors -> tick "Virtualize Intel VT-x/EPT or AMD-V/RVI" # Network -> Bridged, so the address it serves is reachable # 2. inside the guest, prove the passthrough BEFORE installing anything grep -o -m1 -E 'vmx|svm' /proc/cpuinfo # prints vmx, or svm on AMD ls -l /dev/kvm # must exist

If both of those answer, the rest is the Linux page above, unchanged — this is an ordinary Ubuntu server that happens to live in a window:

# 3. as root in the guest cd znetlab/server sudo ./deploy.sh
On a Windows host, Hyper-V and Workstation fight over the processor. With Hyper-V, WSL2, Docker Desktop or Credential Guard enabled, Workstation runs on the Windows Hypervisor Platform instead of its own, and nested virtualisation for guests becomes unreliable or simply absent. Two honest ways out: turn Hyper-V off for the machine that runs Workstation, or stop fighting it and use WSL2, which gives you /dev/kvm anyway — see the Windows page.

The four settings that actually matter, and why:

SettingValueWhy
Virtualization engineVT-x/EPT or AMD-V/RVI, tickedThe only reason to use this platform. Everything else here is ordinary sizing.
Processors4 or moreEach QEMU device wants a core of its own while it boots, and the host keeps one.
Memory8 GB, more per userRoughly 512 MB per IOSv and 4 GB per CSR or Nexus — the guest cannot hand out what it was not given.
Network adapterBridged, not NATAccounts are issued the server address from their plan. Behind NAT that address is reachable from the host and nowhere else, which looks like a broken socket rather than a network choice.

Worth being plain about the shape of this: the VM is the server, not a device. ZNetLab does not drive Workstation and cannot boot a lab device as a Workstation VM — the cabling in a topology is Linux bridges, veth pairs and namespaces inside that one guest, and a vmnet switch on the host has no way into them. Workstation is here because it is the cheapest way to get a kernel that owns /dev/kvm.

AWS — EC2

Read this before you pick an instance. A normal EC2 instance is itself a virtual machine on the Nitro hypervisor, and it does not give you /dev/kvm. Choose a bare-metal instance — anything ending in .metal — or QEMU images run under software emulation, roughly ten times slower. Dynamips, IOL and the built-ins are unaffected.
InstanceKVMGood for
c6i.metal, m5.metalyesA real shared lab server. This is the one to pick.
t3.large, m5.xlargenoFine for built-ins, IOL and Dynamips. Painful for CSR or ASAv.
# 1. launch — Ubuntu 22.04 or 24.04, and give it room for images AMI Ubuntu Server 24.04 LTS (x86_64) Type c6i.metal or m5.metal Storage 200 GB gp3 root; images are 1–4 GB each Key pair your existing one # 2. security group — do NOT open this to the world TCP 8080 source: your office IP/32 ZNetLab itself TCP 22 source: your office IP/32 ssh
# 3. on the instance ssh -i key.pem ubuntu@<public-ip> sudo apt-get update && sudo apt-get install -y git git clone <your znetlab checkout> && cd znetlab/server sudo ./deploy.sh # confirm you really got KVM — this is the whole reason for .metal ls -l /dev/kvm crw-rw---- 1 root kvm 10, 232 /dev/kvm

Two things worth doing on day one, both about the images rather than the server:

Do thisWhy
A separate EBS volume for /opt/znetlab/imagesImages outlive instances. Detach it, attach it to the replacement, and the library survives a rebuild.
A private S3 bucket as the archiveKeep the licensed originals there and pull them down with aws s3 cp instead of re-uploading over ssh every time.
An Elastic IPThe lab address is issued to accounts from their plan. A public IP that changes on every stop breaks every one of them.
A .metal instance is expensive to leave running. Stop it out of hours — the EBS volume and the image library persist.

Azure — Virtual Machines

Azure is the easier of the two clouds for this. Nested virtualization is supported on the ordinary v3-and-newer sizes, so you get /dev/kvm without paying for bare metal.
SizeKVMGood for
D4s_v5, D8s_v5, E8s_v5yesNested virtualization. The normal choice.
B-series (burstable)noAvoid. No nesting, and the CPU credits run out mid-boot.
# 1. create it — Azure CLI, or the same choices in the portal az group create --name znetlab --location centralindia az vm create \ --resource-group znetlab --name znetlab-lab \ --image Ubuntu2404 --size Standard_D8s_v5 \ --admin-username azureuser --generate-ssh-keys \ --os-disk-size-gb 200 # 2. the network security group — your address, not the world az vm open-port --resource-group znetlab --name znetlab-lab --port 8080
# 3. on the VM ssh azureuser@<public-ip> sudo apt-get update && sudo apt-get install -y git git clone <your znetlab checkout> && cd znetlab/server sudo ./deploy.sh # confirm nesting really is on for this size ls -l /dev/kvm && egrep -c "vmx|svm" /proc/cpuinfo
Do thisWhy
A managed data disk for /opt/znetlab/imagesPremium SSD, 256 GB or more. It detaches and reattaches, so the library survives a rebuilt VM.
A private Blob container as the archivePush the licensed originals up once and pull them with azcopy copy straight into the drop folder.
A static public IPSame reason as anywhere: accounts are issued this address from their plan, and a dynamic one breaks them on every deallocate.
Auto-shutdownBuilt into the VM blade. A lab server nobody is using overnight is the easiest money to stop spending.

4First sign-in

The installer prints an address, a username and a password. That account is the only administrator until you make another, and ZNetLab seeds no demo accounts — there is nothing with a default password to forget about.

# what deploy.sh prints when it finishes Sign in at ws://10.0.0.14:8080 Username admin DROP IMAGES HERE /opt/znetlab/images/incoming Log /var/log/znetlab.log

Open the ZNetLab site, sign in with that, and the Accounts tab, the Admin portal and the Images upload appear. Then, in this order:

1. Change the administrator password on the Account tab.
2. Create real accounts on the Accounts tab and set each one’s plan — the plan is what issues them this server’s address.
3. Load your images, which is the next section.

5Host your images

ZNetLab ships no vendor software, and it never will — those images are licensed by their vendors. You put in the ones you are entitled to run. There is one destination and four ways to reach it.

The Images tab, in the browserscp / rsync from your machineExplorer, on Windows (\\wsl$)aws s3 cp · azcopy, in the cloudimages/incoming/one destinationnothing to typewaits until the file stops growingreads the first bytes, not the nameunpacks zip, gz, tar, 7zidentifies it — 120 platformsconverts the disk if it mustfiles it — and it is on the shelf
Four routes in, one folder, one pipeline. You never tell ZNetLab what a file is.
# from your own machine, over ssh scp csr1000vng-17.03.qcow2 root@server:/opt/znetlab/images/incoming/ # on Windows — paste this into Explorer and drag files in \\wsl$\znetlab\opt\znetlab\images\incoming # AWS, from a private bucket aws s3 cp s3://your-images/csr1000vng-17.03.qcow2 /opt/znetlab/images/incoming/ # Azure, from a private container azcopy copy "https://acct.blob.core.windows.net/images/*?SAS" \ /opt/znetlab/images/incoming/ --recursive

Naming is the only thing ZNetLab asks of you, and only when it cannot work the name out itself. Get it right and there is nothing else to configure — RAM, interface naming and which engine runs it all come from the platform it recognises.

# the naming ZNetLab expects — platform, then version vios-15.6.2T QEMU: identity is the DIRECTORY name csr1000vng-17.03.04a i86bi-linux-l2-adventerprisek9-15.2d.bin IOL keeps Cisco’s own naming # it did not recognise one? it does not guess — it sets it aside and says so images/unidentified/ rename it as above and drop it in again
Two builds of one platform never collide. Identity lives in the directory, so library/vios-15.6.2T/ and library/vios-15.9.3/ both stay, and both appear on the shelf.

Want to prove the whole thing before you touch a licensed image? Several genuinely free ones need no licence at all — FRRouting, VyOS, Cumulus VX, Arista vEOS, pfSense CE, OPNsense, Alpine and Ubuntu Server. Drop one in and watch it come out on the shelf.

6Prove it works

A lab server that looks up but silently does not forward traffic is the worst outcome, so ZNetLab ships two checks and the installer runs both. Run them yourself whenever you change the host.

# 1. the kernel — bridges, veth, namespaces, tun, kvm sudo ./verify.sh # 2. the running server — drives it over the socket and checks the # kernel actually agrees with what it claims node verify-lab.js ws://127.0.0.1:8080 admin <password>

Then the human check, which takes a minute: build two Virtual PCs and a LAN Switch, start it, and ping across. No image, no licence — if that works, the datapath works.

7Keep it running

WantDo
Start at bootsystemctl enable --now znetlab — the unit is written for you. Not available under WSL2, which has no systemd.
Watch itjournalctl -u znetlab -f, or tail -f /var/log/znetlab.log
See what is runningThe Admin portal — every lab, whose it is, and how much it is using.
Back it up/var/lib/znetlab. Accounts, saved labs and the activity trail live there and cannot be recreated. Images can always be copied again.
Move the libraryPoint --images at another disk. Put it on its own volume from the start and a rebuild costs you nothing.

8Lock it down

DoWhy
Do not open 8080 to the internetRestrict the security group, NSG or firewall to the addresses that need it. This is the single most important line on this page.
Put TLS in front of itnginx or Caddy terminating wss://, or a VPN. Credentials and console traffic both cross this socket.
Change the first passwordThe installer’s password was printed on a terminal, and on WSL2 it was generated into a scrollback buffer.
Keep /var/lib/znetlab at 700deploy.sh sets it. Password hashes and the activity trail are in there.
Give people the plan they needPlan ceilings are enforced on the server, not in the browser. They are what stops one account exhausting the memory everybody shares.
Keep an eye on the licencesZNetLab counts nothing for you here. The images are yours, and so is the entitlement to run them.
Everything on this page is administrator work. The people building labs never see any of it — they sign in, and their plan hands them this server.

Generated by tools/guide-pdf.js from the guide functions in lab/assets/app.js, the icon set in assets/icons.js and the plan table in assets/plans.js — the same plan table the server enforces. Every screen, button, path, port, command and ceiling named above is read out of the running product rather than transcribed, so this document goes stale only when the product does. Part I's plan tables are shown for the Free plan, which carries the tightest ceilings of any.