Setup

build docker image for linux:

cd ~/labs/sshworkshop
docker build -t workshop-debian:v1 .

import arista cEOS image

docker image import ~/cEOS64-lab-4.32.0.1F.tar.xz ceos-lab:4.32.0.1F

generate/ready the list of names:

cp namepicker/names.yml ~/labs/sshworkshop/names-hashes.yml

bridges on clab host

apt install bridge-utils

auto br-ext
iface br-ext inet static
    address 10.192.40.1/29
    bridge-ports none
    bridge-stp off
    bridge-fd 0

auto br-clab-intonly
iface br-clab-intonly inet manual
    bridge-ports none
    bridge-stp off
    bridge-fd 0

ifup br-ext ifup br-clab-intonly

DNAT & Co

edit & run ./setups/hypervisor.sh (change UPLINK_INTERFACE accordingly)

#!/usr/bin/env bash
UPLINK_INTERFACE="enp0s31f6"

for port in {4010..4200}; do
    ip_octet=$((port - 4000))               # 4011 → 11, … 4200 → 200
    dst_ip="192.168.0.${ip_octet}"

    iptables -t nat -A PREROUTING \
        -i "$UPLINK_INTERFACE" -p tcp -m tcp --dport "$port" \
        -j DNAT --to-destination "${dst_ip}:22"
done
iptables -t nat -A POSTROUTING     -o br-ext -p tcp -d 192.168.0.0/24 --dport 22     -j MASQUERADE

Deploy

containerlab (via vscode) & go. it takes a good minute (with 50 workstations) for the setup to be ready (DHCP etc). to create a csv of the online-users, run echo "IP,host,username,pwd"; cat online-users.txt | awk -F' +' 'BEGIN{OFS=","} {$1=$1; print}' on linux-gateway.

prep workshop

once the lab is deployed and the online-users.txt is built, generate the cards to print out:

generate CSV

(echo "IP,host,username,pwd"; cat online-users.txt | awk -F' +' 'BEGIN{OFS=","} {$1=$1; print}') > credentials.csv

csv2cards script

#!/usr/bin/env bash
# csv2cards.sh → html
CSV=${1:-credentials.csv}
OUT=${2:-cards.html}

# start the document
cat >"$OUT" <<'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Credentials cards</title>
<style>
  @page { size: A4 portrait; margin: 1cm; }
  body { font-family: monospace; display: flex; flex-wrap: wrap; gap: 0.5cm; }
  .card {
    width: 9cm;               /* fits 23 cards across A4 */
    border: 1px solid #333;
    padding: 0.3cm;
    box-sizing: border-box;
    page-break-inside: avoid;
  }
  .field { margin: 0.1cm 0; }
  .label { font-weight: bold; }
</style>
</head>
<body>
EOF

# read CSV, skip header, emit a <div class="card"> per line
awk -F',' 'NR>1{
    printf "<div class=\"card\">\n"
    printf "  <div class=\"field\"><span class=\"label\">IP:</span> %s</div>\n", $1
    printf "  <div class=\"field\"><span class=\"label\">Host:</span> %s</div>\n", $2
    printf "  <div class=\"field\"><span class=\"label\">User:</span> %s</div>\n", $3
    printf "  <div class=\"field\"><span class=\"label\">Pass:</span> %s</div>\n", $4
    printf "</div>\n"
}' "$CSV" >>"$OUT"

# close the document
cat >>"$OUT" <<'EOF'
</body>
</html>
EOF

download html, print from browser. Should be automatically A4.

Description
No description provided
Readme 7.2 MiB
Languages
Shell 55.2%
Python 40.4%
Dockerfile 1.8%
JavaScript 1.3%
Less 0.7%
Other 0.6%