This is an old revision of the document!
Table of Contents
EVE-OS / ZEDEDA Hardware Model Creation
This page documents how to build a ZEDEDA Cloud hardware model for a new edge node, including a simpler alternative to the USB-round-trip and console/debug-shell methods.
The problem
The two ways most people reach for to pull hardware spec info off a node running EVE-OS are:
- USB install method — boot the EVE-OS installer from USB; EVE-OS writes a best-effort model file back to the inventory partition of the USB stick. Requires physically getting the USB stick back after install.
- Console + debug shell method — get serial/KVM console access, drop into the EVE-OS debug shell, and run
spec.shmanually. Requires ongoing console/KVM access to the device.
Both are fine if you have that physical/console access. The real problem shows up when you don't: a remote site, a device with no console port wired up, no one on hand to swap the USB stick back out, etc. In that case you're stuck — you can't SSH in to grab the info remotely, because SSH normally isn't available until the node is onboarded, and it can't be onboarded without knowing its hardware model.
There's actually a third, less well-known official option that solves exactly this: an EVE-OS installer image with SSH bootstrapped in. It still needs one physical flash-and-boot, but after that everything else — pulling spec.sh, lspci, etc. — happens over the network.
The simpler way: SSH-enabled EVE-OS image
You don't actually need onboarding to get SSH. EVE-OS supports a bootstrap SSH config baked into the installer image itself, via files placed on the config partition before flashing. This gets you a root shell over the network the moment the node boots — no console, no USB round-trip, no onboarding.
Prerequisites
- Docker running on your workstation.
- An SSH keypair (
ssh-keygen -t ed25519if you don't have one).
Steps
- Create the config staging directory:
mkdir -p /tmp/config/GlobalConfig
- Drop your public key in as
authorized_keys:
PUBLIC_KEY_PATH=~/.ssh/id_ed25519.pub cat "$PUBLIC_KEY_PATH" > /tmp/config/authorized_keys
- Add the controller FQDN in a
serverfile:
cat <<EOF > /tmp/config/server zedcloud.zededa.net EOF
- Enable SSH via
GlobalConfig/global.json(this file must exist for EVE-OS to load the bootstrap config at all):
cat <<EOF > /tmp/config/GlobalConfig/global.json { "GlobalSettings": { "debug.enable.ssh": { "Key": "debug.enable.ssh", "ItemType": 3, "StrValue": "$(cat "$PUBLIC_KEY_PATH")" } } } EOF
''ItemType: 3'' = string value; ''debug.enable.ssh'' holds the actual public key, not a boolean.
- Build the installer image with the config folder mounted in:
docker run -v /tmp/config:/in --rm lfedge/eve:latest installer_raw > installer-ssh.raw
- Flash
installer-ssh.rawto USB and boot the target device.
- SSH straight in:
ssh -i ~/.ssh/id_ed25519 root@<DEVICE_IP>
Note: this bootstrap SSH access only works before onboarding. Once the node onboards, these settings are ignored. If you want to keep SSH access afterward, re-enable it through ZCLI:
zcli edge-node update <edge-node-name> --config="debug.enable.ssh:$(cat ~/.ssh/id_ed25519.pub)"
Gathering the hardware spec over SSH
Once you have a shell, pull the same information the console/debug-shell method would give you, without needing physical access at all.
Get the best-effort model JSON
spec.sh
This produces a JSON blob (CPU count, memory, storage, and an ioMemberList of guessed adapters — VGA, USB, COM ports, NVMe, Ethernet, etc.). Save it, e.g. as MyModel.json. Treat it as a draft — EVE-OS's guesses are “best effort” and usually need correcting.
Validate/correct each adapter
- Remove logo placeholders —
logo_back/logo_frontdefault to placeholder paths; blank them out or you'll get a cosmetic error. - PCI devices (VGA, USB, Ethernet, etc.):
lspci -k
- IOMMU groupings (which devices share a passthrough group — matters for
assigngrp):
find /sys/kernel/iommu_groups/ -type l
- Serial/COM ports:
dmesg | grep -i ttyS
- USB topology (to confirm which physical port maps to which controller):
lsusb
lsusb -t
Cross-check each entry in the ioMemberList against this output:
- Fix or fill in empty
PciLong/Ioports/assigngrpvalues. - Delete entries for ports that don't actually exist as separate controllers (e.g., a device with 4 physical USB ports but only 1-2 controllers in
lspci/iommu output — the extra logical entries should be removed since they can't be independently passed through). - Omit adapters you don't intend to model (e.g., NVMe, if not relevant).
Validate the final file with a JSON linter before uploading.
Uploading the model to ZEDEDA Cloud (ZCLI)
- Copy the validated JSON into the ZCLI docker container:
docker cp /path/to/MyModel.json docker_containerID:/home/zcli
- Create the hardware brand, if it doesn't already exist:
zcli brand create NAME --title=TITLE
- Create the model, linking it to the JSON:
zcli model create NAME --hardware-details=PATH/TO/JSON --brand=BRAND [--title=TITLE]
- To revise a model later, edit the JSON and:
zcli model update NAME [--hardware-details=PATH/TO/JSON] [--brand=BRAND] [--title=TITLE]
Changes propagate to every edge node currently using that model.
Onboarding the node
With the model created, onboard the edge node in ZEDEDA Cloud (GUI or ZCLI): pick the Brand/Model, choose a Hardware Identity method (Edge Node Certificate from the USB inventory partition, Onboarding Key + serial number, or a single-use installer), and finish the flow.
Good to know: for lab/test nodes, ZEDEDA Cloud lets you onboard with *any* placeholder model just to get connectivity up — you don't strictly need the final model in hand before the first boot. That's a second way to sidestep the chicken-and-egg problem: onboard with a generic model + Onboarding Key/soft-serial (no cert extraction needed at all), then once online, correct/replace the model later. The SSH-image method above is still preferable when you want the *real* model nailed down before onboarding at all, e.g. for image reuse across a fleet of identical devices.
Method comparison
| Method | Needs console/KVM | Needs USB round-trip | Needs onboarding first | Notes |
|---|---|---|---|---|
| USB install dump | No | Yes | No | Best-effort model written back to USB inventory partition |
| Console + spec.sh | Yes | No | No | Manual, slow, needs physical/remote KVM access |
| SSH-enabled image | No | No (still need to flash once) | No | Recommended — full shell access pre-onboarding |
| Onboard w/ generic model | No | No | N/A (this *is* onboarding) | Fastest to get connectivity; still need to fix model later |
