Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Network Automation Lab

Your hands-on networking playground. Containerlab on Hetzner VPS with Nokia SR Linux, FRR, and Python automation.

Quick Start

# SSH into the lab
clab

# See topology
clab inspect

# Open topology web viewer
clab web

# Deploy the lab
clab deploy

# Destroy the lab
clab destroy

What's Running

Node Type OS Purpose How to Access
router Nokia SR Linux SR Linux v26.3.2 Core routing, NETCONF/YANG, VXLAN/EVPN sr_cli (interactive CLI)
frr Alpine Linux FRR 10.5.3 BGP/OSPF routing, Linux networking vtysh or sh
h1 Alpine Linux Linux Traffic generator, test host sh
h2 Alpine Linux Linux Traffic generator, test host sh
toolkit Alpine Linux Python 3.8 Automation scripts, YANG tools python3

Manual Usage (Like CML)

Accessing Devices

From your Mac, you can access any lab node directly:

# SR Linux CLI (like Cisco's enable mode)
clab "docker exec -it clab-network-lab-router sr_cli"

# Once in sr_cli:
/interface ethernet-1/1 admin-state enable
/interface ethernet-1/1 subinterface 0 ipv4 address 10.0.0.1/24
commit now
show version
info from state /interface ethernet-1/1

# Bash shell inside SR Linux
clab "docker exec -it clab-network-lab-router bash"
# From bash: ip addr show, ping, tcpdump, etc.

# FRR router - Alpine shell
clab "docker exec -it clab-network-lab-frr sh"
# From shell: vtysh (routing CLI), ip link, ping

# FRR routing CLI (vtysh - like Cisco IOS)
clab "docker exec -it clab-network-lab-frr vtysh"
# From vtysh:
#   show ip route
#   show bgp summary
#   configure terminal
#   router bgp 65000
#    neighbor 10.0.0.2 remote-as 65000

# Hosts - Alpine shell
clab "docker exec -it clab-network-lab-h1 sh"
# From shell: ping, iperf3, curl, wget

# Toolkit - Python automation hub
clab "docker exec -it clab-network-lab-toolkit sh"
# From shell: python3, ncclient, pyang, netmiko

Shortcut Commands (Run from your Mac)

# List all nodes
clab inspect

# Run one command on a specific node
clab "docker exec clab-network-lab-router sr_cli -c 'show version'"
clab "docker exec clab-network-lab-frr ip addr show"

# Ping between nodes
clab "docker exec clab-network-lab-h1 ping 10.0.0.10"

# View logs
clab "docker logs clab-network-lab-router"

# Live topology graph
clab web   # Opens http://46.225.27.145:50080

# Check resource usage
clab "free -h && docker stats --no-stream"

Quick Reference: SR Linux CLI

# Enter CLI
docker exec -it clab-network-lab-router sr_cli

# Show commands
show version
show /interface brief
show /system network-instance brief
show /system network-instance default protocol bgp neighbor

# Configure
/interface ethernet-1/1
  admin-state enable
  subinterface 0
    ipv4 address 10.0.0.1/24
commit now

# Network instance (like VRF)
/network-instance default
  interface ethernet-1/1.0
commit now

# Run Linux commands from sr_cli
bash
  ip addr show
  ping 10.0.0.1
exit

# Save/show config
save /tmp/config.json
info from running

YANG + NETCONF

SR Linux has NETCONF enabled by default on port 830. Run Python directly on the VPS host (ncclient + pyang already installed):

# SSH into VPS
clab

# Test NETCONF connection to SR Linux router
python3 << 'EOF'
from ncclient import manager
conn = manager.connect(
    host="172.20.20.2",   # router's IP on clab network
    port=830,
    username="admin",
    password="NokiaSrl1!",
    hostkey_verify=False,
    allow_agent=False,
    look_for_keys=False
)
print("NETCONF connected!")
print("Server capabilities:", len(conn.server_capabilities), "capabilities")
for cap in list(conn.server_capabilities)[:5]:
    print(" ", cap)
result = conn.get(filter=('xpath', '/system/version'))
print(result.xml[:500])
conn.close_session()
EOF

# Get full running config as XML
python3 << 'EOF'
from ncclient import manager
m = manager.connect(host="172.20.20.2", port=830, username="admin",
    password="NokiaSrl1!", hostkey_verify=False, allow_agent=False, look_for_keys=False)
result = m.get_config(source="running")
import xml.dom.minidom
print(xml.dom.minidom.parseString(result.xml).toprettyxml()[:3000])
m.close_session()
EOF

# Push a config change via NETCONF
python3 << 'EOF'
from ncclient import manager
m = manager.connect(host="172.20.20.2", port=830, username="admin",
    password="NokiaSrl1!", hostkey_verify=False, allow_agent=False, look_for_keys=False)
config = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interface xmlns="urn:nokia.com:srlinux:naas:interfaces">
    <ethernet-1/2>
      <admin-state>enable</admin-state>
    </ethernet-1/2>
  </interface>
</config>
'''
reply = m.edit_config(target="candidate", config=config)
print("Edit:", reply.ok)
m.commit()
print("Commit: OK")
m.close_session()
EOF

Adding More Vendor Devices

Nokia SR Linux ✅ Already Available

kind: srl
image: ghcr.io/nokia/srlinux:latest
type: ixr-d2l

No account needed. Just add to any topology.

Arista cEOS (needs Arista account)

  1. Register at https://www.arista.com/en/user-registration
  2. Log in to https://www.arista.com, download cEOS image
  3. Load into Docker: docker import cEOS-lab.tar.xz ceos:latest
  4. Add to topology:
leaf-arista:
  kind: ceos
  image: ceos:latest

Juniper cJunos (needs Juniper support account)

  1. Register at https://www.juniper.net/us/en/user-registration
  2. Download vJunos image from Juniper support
  3. Load into Docker: docker load -i vjunos-switch.img
  4. Add to topology:
leaf-junos:
  kind: juniper_vjunosswitch
  image: juniper/vjunos-switch:latest

Cisco IOS-XR (needs Cisco CCO account)

  1. Register at https://cisco.com
  2. Download IOS-XRv image
  3. Use vrnetlab to wrap it:
leaf-xr:
  kind: vr-xrv9k
  image: vrnetlab/vr-xrv9k:700

Open Source Option: SONiC

leaf-sonic:
  kind: linux
  image: sonic:latest

Build your own Docker image from https://github.com/sonic-net/SONiC


VXLAN/EVPN Configuration (Modern Networking)

On FRR (leaf-1 in a spine-leaf topology)

# Enter FRR CLI
clab "docker exec -it clab-network-lab-frr vtysh"

# Configure BGP EVPN with VXLAN
configure terminal
router bgp 65000
 bgp router-id 10.0.0.2
 neighbor 10.0.0.1 remote-as 65000
 address-family l2vpn evpn
  neighbor 10.0.0.1 activate
  advertise-all-vni
 exit-address-family
exit

# Create VXLAN interface
ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.0.0.2 nolearning
ip link set vxlan10 up
ip addr add 192.168.10.1/24 dev vxlan10

On SR Linux

# Enter SR Linux CLI
clab "docker exec -it clab-network-lab-router sr_cli"

# Configure BGP EVPN
/network-instance default
  protocols bgp
    group evpn-peers
      admin-state enable
      peer-as 65000
      local-as 65000
      transport local-address 10.0.0.1
    neighbor 10.0.0.2
      peer-group evpn-peers

# Configure VXLAN interface
/tunnel-interface vxlan1
  type vxlan
  vxlan
    vni 10
    ingress-src-ip 10.0.0.1
commit now

Terraform (Infrastructure as Code)

The VPS itself is provisioned via Terraform:

cd ~/Documents/network-lab/terraform

# View plan
terraform plan -var="hcloud_token=$HCLOUD_TOKEN"

# Apply (provision)
terraform apply -var="hcloud_token=$HCLOUD_TOKEN"

# Tear down (DANGER - deletes the VPS)
terraform destroy -var="hcloud_token=$HCLOUD_TOKEN"

Infrastructure specs:

  • Server type: CX23 (2 vCPU, 4 GB RAM, ~€5.80/mo)
  • Location: nbg1 (Nuremberg)
  • Image: Ubuntu 24.04
  • Cloud-init: Auto-installs Docker, containerlab, Python stack
  • Labels: purpose=network-automation-lab
  • Protection: delete_protection=true (prevents accidental destruction)

To upgrade the server (e.g., to CX33 for more devices):

# In terraform/variables.tf, change:
variable "server_type" {
  default = "cx33"  # 4 vCPU, 8 GB RAM, ~€9.30/mo
}
# Then: terraform apply

Lab Directory Structure

~/Documents/network-lab/
├── labs/
│   ├── 00-ospf-basics/     # Alpine + manual routing
│   └── 01-core-lab/        # SR Linux + FRR (current)
│   └── 02-evpn-lab/        # BGP EVPN + VXLAN (future)
│   └── 03-yang-lab/        # YANG/NETCONF deep dive (future)
├── terraform/
│   ├── main.tf              # Hetzner server resource
│   ├── variables.tf         # Configurable variables
│   ├── outputs.tf           # Server IP, SSH command
│   └── cloud-init.yaml      # Bootstrapping script
├── automation/              # Python scripts (future)
├── docs/                    # Session notes, reference
├── Makefile                 # All commands
└── README.md                # This file

Makefile

cd ~/Documents/network-lab
make help           # List all commands
make deploy         # Deploy the core lab
make cleanup        # Destroy the lab
make inspect        # Show running nodes
make install-all    # Install local tools
make pull-images    # Pull container images
make tf-plan        # Terraform plan
make tf-apply       # Terraform apply
make tf-destroy     # Terraform destroy
make tf-ssh         # SSH into the VPS
make tf-sync        # Sync labs to VPS

Resource Limits

Lab Size Nodes Memory RAM on CX23 Works?
Minimal (current) 1 SRL + 1 FRR + 2 hosts + toolkit ~1.2 GB 4 GB ✅ Yes
Medium 3 SRL + 3 FRR + hosts ~3.0 GB 4 GB ⚠️ Tight
Large (EVPN) 1 spine + 2 leaf SRL + 4 hosts ~2.8 GB 4 GB ⚠️ Try CX33

For larger labs, upgrade to CX33: edit terraform/variables.tf and change server_type to cx33, then make tf-apply.

AI Integration

This lab is fully accessible from Hermes Agent via MCP (Model Context Protocol). You can manage the entire lab in natural language.

Hermes MCP Commands

Already configured in ~/.hermes/config.yaml — just ask:

How many nodes are running in my lab?
Show me the SR Linux version
NETCONF get the interface config
What's the lab health status?

CLI Tool (lab-cli)

lab-cli topology              # List running nodes
lab-cli router_cmd 'show version'  # SR Linux CLI
lab-cli frr_cmd 'show ip route'    # FRR CLI
lab-cli netconf_get           # Full config via NETCONF
lab-cli lab_status            # System health + reachability
lab-cli netconf_get '<interface xmlns="urn:nokia:srlinux:netw:if"/>'  # Filtered NETCONF

Web Dashboard

Open in browser: http://46.225.27.145:8080

Or via the shortcut:

clab dashboard    # Opens in browser

The dashboard provides:

  • Topology view — live node cards with IPs and status (auto-refresh every 15s)
  • Command Runner — SR Linux CLI, FRR CLI, host shell, all from the browser
  • NETCONF Playground — full NETCONF get/edit on SR Linux with preset filters
  • Lab Status — system resources, device reachability, software versions

Auto-starts on VPS boot via systemd service.

Architecture

You (Hermes chat / CLI) ── SSH ── VPS MCP Server ── Docker exec/NETCONF ── Lab Nodes
                                ├─ Web Dashboard (port 8080)
                                └─ Topology Graph (port 50080)

The MCP server lives on the VPS and exposes 7 tools. Hermes connects via SSH stdio transport — zero dependencies on the Mac side.

Service Management

# Dashboard (systemd)
clab "systemctl status network-lab-dashboard"

# Topology graph
clab graph    # Starts on port 50080

# MCP server (auto via Hermes config)
clab mcp      # List available tools

GitHub

Repo: https://github.com/Radmanded/network-lab

The Terraform configs, lab topologies, and this guide are all version-controlled. Clone anywhere:

git clone https://github.com/Radmanded/network-lab
cd network-lab
# Edit terraform/variables.tf → set hcloud_token
make tf-apply

About

Network Automation Lab - YANG/NETCONF/RESTCONF with Containerlab on Hetzner VPS (Terraform provisioned)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages