Important
AI-GENERATED PROJECT NOTICE
This project was fully generated by Artificial Intelligence (AI).
🚫 NO PULL REQUESTS WILL BE ACCEPTED.
If you wish to contribute, you are welcome to open an issue for discussion or donate to the project author to help cover AI token costs.
Warning
LINUX ONLY SUPPORTED
netlabctl is supported on Linux operating systems ONLY (requires Linux KVM / QEMU tap & socket networking). Windows and macOS are NOT supported.
netlabctl is a simple, lightweight, and easy-to-use web-based network lab simulator. It provides a visual canvas UI to design, wire, and execute virtual network topologies powered by QEMU.
netlabctl is created specifically for teaching and learning networking (routing, firewalls, switching, and lab experimentation).
It is NOT intended to be a replacement for heavy enterprise network simulation platforms such as GNS3, EVE-NG, containerlab, or Cisco VIRL. Instead, netlabctl focuses on rapid setup, minimal resource overhead, and a zero-friction browser experience.
- Interactive Canvas UI: Multi-tool canvas powered by Fabric.js with non-crossing Manhattan wire routing, dynamic zoom/pan, and tool mode isolation (
Selectvs.Wire). - Unrestricted QEMU Engine: Although simple to use,
netlabctlis not limited. Any OS or machine architecture supported by QEMU (MikroTik RouterOS, Debian, Ubuntu, OpenWrt, FreeBSD, Custom ISOs/QCOW2s) can be simulated. - Embedded Device Templates: Pre-packaged templates embedded directly inside the binary (MikroTik 4/8/16/32/64-port, Debian 13, etc.) with automatic template tab grouping in the Add Device modal.
- Dedicated Disk Storage: Centralized image directory at
~/.netlabctl/images/with visual disabled opacity filters and warnings for missing disk images. - Real-Time Serial Console: Web-based
xterm.jsterminal over WebSockets with automatic standby polling and reconnect telemetry when VMs boot up. - Cloud-Init (NoCloud): Automatic generation of
cidata.isofor userdata and metadata cloud-init scripts with{{{ node.var }}}template placeholders. - Packet Mirroring (TZSP): Per-port UDP TZSP frame forwarding targets.
- Full Project Lifecycle: Multi-lab project switcher with Rename, Import (
topology.json), and Export features. - Interactive Swagger UI: Full OpenAPI 3.0 interactive documentation and testing suite served at
/swagger.
netlabctl provides a complete REST API and WebSocket interface. Interactive Swagger UI is built directly into the server:
- Swagger UI Interactive Docs:
http://localhost:8080/swagger(orhttp://localhost:8080/docs) - OpenAPI 3.0 JSON Spec:
http://localhost:8080/swagger/doc.json(or/api/docs/openapi.json) - Markdown API Reference: See
docs/API.mdfor full endpoint schemas and WebSocket protocol specification.
netlabctl automatically generates a NoCloud Cloud-Init ISO (cidata.iso) when userdata or metadata scripts are specified on device templates or node properties.
To insert dynamic values into your scripts, wrap variable names in triple curly braces {{{ variable }}}:
| Placeholder | Description | Example Output |
|---|---|---|
{{{ node.id }}} |
Unique node identifier | node-1 |
{{{ node.name }}} |
Display name of the machine | Router-A |
{{{ node.memory }}} |
Allocated RAM memory in Megabytes | 256 |
{{{ node.smp }}} |
Allocated vCPU cores | 2 |
{{{ port0.mac }}} or {{{ node.ports[0].mac }}} |
MAC address of interface port index 0 | 52:54:00:12:34:56 |
{{{ port1.mac }}} or {{{ node.ports[1].mac }}} |
MAC address of interface port index 1 | 52:54:00:12:34:57 |
{{{ port0.name }}} or {{{ node.ports[0].name }}} |
Name of interface port index 0 | eth0 |
Note
Placeholders MUST use triple curly braces {{{ ... }}}. Dollar signs ($) and single brackets ({ ... }) are not used as variable delimiters.
#cloud-config
hostname: {{{ node.name }}}
fqdn: {{{ node.name }}}.local
manage_etc_hosts: true
users:
- name: netlab
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
runcmd:
- echo "Configuring {{{ node.name }}} ({{{ node.id }}})"
- ip link set eth0 address {{{ port0.mac }}}Download the latest Linux binary directly from the GitHub Releases page:
chmod +x netlabctl
./netlabctlOpen http://localhost:8080 in your web browser.
- Linux OS (Ubuntu 22.04+, Debian 12+, Arch Linux, Fedora, etc.)
- Go 1.22 or higher
- Node.js 18+ and npm
- QEMU:
qemu-system-x86_64(sudo apt install qemu-system-x86_64) - ISO Creation Utility:
genisoimage,mkisofs, orxorriso(for Cloud-Init ISO generation)
-
Clone the Repository:
git clone https://github.com/your-user/netlabctl.git cd netlabctl -
Build the Web Frontend:
cd client npm install npm run build cd ..
-
Build the Go Binary:
go build -o netlabctl ./cmd/netlabctl
-
Run netlabctl:
./netlabctl -addr ":8080"Navigate to
http://localhost:8080in your browser.
netlabctl uses modular device templates stored in $HOME/.netlabctl/devices/ with centralized QCOW2 disk images stored in $HOME/.netlabctl/images/.
netlabctl requires QCOW2 format disk images. If your operating system disk image is in RAW (.img / .raw), VMDK, or VDI format, convert it using qemu-img:
qemu-img convert -f raw -O qcow2 input-disk.raw ~/.netlabctl/images/my-custom-os.qcow2qemu-img convert -f vmdk -O qcow2 input-disk.vmdk ~/.netlabctl/images/my-custom-os.qcow2qemu-img convert -f vdi -O qcow2 input-disk.vdi ~/.netlabctl/images/my-custom-os.qcow2Tip
Always place your target .qcow2 files directly inside $HOME/.netlabctl/images/.
Create a subdirectory under $HOME/.netlabctl/devices/ for your custom template:
mkdir -p ~/.netlabctl/devices/my-custom-osEach template folder requires two files:
machine.json: Device specifications, RAM, vCPUs, QEMU binary, cloud-init defaults, and network interface definitions.drawing.svg: Vector graphic illustration representing the device front panel on the topology canvas.
Create ~/.netlabctl/devices/my-custom-os/machine.json:
{
"id": "my-custom-os",
"name": "My Custom Linux OS",
"description": "Custom Linux Appliance with 2 VirtIO network interfaces",
"group": "Linux",
"image": "my-custom-os.qcow2",
"drawing": "drawing.svg",
"system": "qemu-system-x86_64",
"memory": 512,
"smp": 2,
"userdata": "#cloud-config\nchpasswd:\n list: |\n root:insecure\n expire: False",
"ports": [
{
"id": "device-port-1",
"name": "eth0",
"device": "virtio-net-pci"
},
{
"id": "device-port-2",
"name": "eth1",
"device": "virtio-net-pci"
}
],
"status": [
{
"id": "device-name",
"type": "name"
},
{
"id": "device-power",
"type": "power"
}
]
}Create ~/.netlabctl/devices/my-custom-os/drawing.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 60">
<rect x="0" y="0" width="200" height="60" fill="#1e293b" rx="6" stroke="#334155" stroke-width="2" />
<circle id="device-power" cx="15" cy="15" r="5" fill="#ef4444" />
<text id="device-name" x="30" y="20" fill="#f8fafc" font-family="sans-serif" font-size="12">My Custom OS</text>
<g class="device-ports">
<rect id="device-port-1" x="30" y="30" width="30" height="20" fill="#475569" stroke="#64748b" rx="2" />
<rect id="device-port-2" x="70" y="30" width="30" height="20" fill="#475569" stroke="#64748b" rx="2" />
</g>
</svg>Once saved, restart netlabctl or open the canvas—your new custom device template will immediately appear in the Add Device modal under its designated group tab!
This project is free and open-source software released under the MIT License.
Caution
DISCLAIMER & WARRANTY NOTICE
netlabctl is COMPLETELY UNSUPPORTED. It is provided "AS IS" WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to fitness for a particular purpose or non-infringement.
Everyone is strongly encouraged to FORK THIS REPOSITORY and build their own customized version of the tool!
