Software

Software setup, configuration, and usage for the Cruiser Carrier Board.

Operating System

The Cruiser is designed to work with Raspberry Pi OS (recommended) or other Debian-based Linux distributions for CM5. No custom OS image is required.

Firmware

Board firmware is pre-flashed at the factory. The ESP32-C6 module ships with the WiFi + Bluetooth firmware, which also handles board control functions (PoE management, etc.). A separate Zigbee coordinator firmware (beta) is available on request - the module has one 2.4 GHz radio and a Zigbee coordinator cannot reliably share it with WiFi, so you choose one image. See the ESP32 Wireless Module page.

Firmware Updates

You can update the ESP32 PoE firmware on your Cruiser with exaviz-flash:

sudo apt update
sudo apt install exaviz-tools
sudo exaviz-flash update

It takes about a minute, backs up your current firmware first, and your PoE devices lose power while it runs. See Firmware Updates for what to expect, how to recover from a failed update, and troubleshooting.

Released firmware versions are listed on the Product Changelogs page.

Drivers and Software

Hardware support is provided through:

  • Mainlined drivers — Most functionality works with standard Linux kernels
  • Exaviz packages — Additional drivers and tools for full functionality

Available Packages

PackageDescription
exaviz-dkmsKernel modules for Cruiser hardware (required)
exaviz-pse-dkmsIP808AR PoE driver — required if using the Interceptor PoE Add-on Board
exaviz-netplanNetwork configuration for WAN port and PoE switch
exaviz-poe-toolPoE port monitoring and control: a GTK3 desktop app and exaviz-poe-tui, a terminal UI and scriptable command line that needs no desktop

Adding the Exaviz Repository

# Download and install the Exaviz signing key
curl -fsSL https://apt.exaviz.com/exaviz-repo-key.asc | sudo gpg --dearmor -o /usr/share/keyrings/exaviz-archive-keyring.gpg

# Detect distribution and add the repository
DISTRO=$(lsb_release -cs 2>/dev/null || (grep VERSION_CODENAME /etc/os-release 2>/dev/null | cut -d= -f2) || echo "trixie")
echo "deb [arch=arm64 signed-by=/usr/share/keyrings/exaviz-archive-keyring.gpg] https://apt.exaviz.com ${DISTRO} main" | sudo tee /etc/apt/sources.list.d/exaviz.list

# Update package lists
sudo apt update

The script automatically detects your distribution:

  • Raspberry Pi OS Trixie → uses trixie
  • Debian 13 (Trixie) → uses trixie
  • Debian 12 (Bookworm) → uses bookworm (still supported through our apt packages; only the Exaviz Bookworm OS image is deprecated)
  • Ubuntu 25.10 (Questing) → uses questing
  • Ubuntu 26.04 LTS (Resolute) → uses resolute

Installing Packages

Minimum installation (drivers only):

sudo apt install exaviz-dkms

The exaviz-dkms package provides:

  • PoE switch drivers (RTL8365MB)
  • DSA framework support for switch management
  • Device tree overlays for CM5

Recommended installation (drivers + network configuration):

sudo apt install exaviz-dkms exaviz-netplan

The exaviz-netplan package:

  • Configures switch and PoE port interfaces
  • Sets up PoE switch port interfaces
  • Optionally runs a DHCP server for connected PoE devices

Full installation (all packages):

sudo apt install exaviz-dkms exaviz-netplan exaviz-poe-tool

The exaviz-poe-tool package provides a graphical interface for:

  • Real-time PoE port status monitoring, with ports listed in order
  • Viewing power consumption per port
  • Seeing which af or at mode each port is currently on
  • Resetting individual ports
  • Temperature and voltage monitoring
  • An Updated column showing how long ago each row last received real data, so a reading that has stopped refreshing cannot be mistaken for a live one

After installation, reboot to load the modules:

sudo reboot

Verify modules are loaded:

lsmod | grep -E "rtl8365mb|realtek"

You should see rtl8365mb and either realtek_smi (kernel 6.8+) or realtek_dsa (older kernels).

  1. Flash Raspberry Pi OS (64-bit) or Debian Trixie to your CM5
  2. Boot and complete initial setup
  3. Add the Exaviz repository and install packages:
    sudo apt install exaviz-dkms exaviz-netplan exaviz-poe-tool
    
  4. Reboot

Network Configuration

Network Interfaces

InterfaceDescriptionDefault
eth0CM5 built-in 1GbE → RTL8367RB switch (internal)Auto-configured
eth12.5GbE WAN port (J15)Requires manual configuration
poe0-poe7Switch ports (J16)*Configured by exaviz-netplan

Configuring the Upstream / WAN Port (eth1)

The eth1 interface (2.5GbE WAN port, RTL8156BG) is not configured by exaviz-netplan and requires manual setup. To bring it up with DHCP:

sudo ip link set eth1 up
sudo dhclient eth1

For a persistent configuration, add a Netplan file:

# /etc/netplan/10-wan.yaml
network:
  version: 2
  ethernets:
    eth1:
      dhcp4: true
sudo netplan apply

Configuring the Switch Network (IP Cameras)

The switch ports (poe0-poe7*) are connected to the CM5 through an internal Ethernet switch using Linux DSA (Distributed Switch Architecture). By default, devices connected to the switch ports are on a separate network segment from your main network.

*Port count depends on model: 8 ports on Cruiser, 4 ports (poe0-poe3) on Cruiser Lite and Keel.

The exaviz-netplan package configures a DHCP server for connected PoE devices. During installation, you select which ports should provide DHCP addresses. Connected devices (cameras, etc.) will automatically receive IP addresses.

sudo apt install exaviz-netplan

To reconfigure later:

sudo dpkg-reconfigure exaviz-netplan

Manual Setup

If you prefer manual control or need a non-standard configuration:

Quick test with static IP:

  1. Find the address on the PoE port your camera is plugged into (here, poe0):

    ip addr show poe0
    

    If the port has no address (manual setup, with no DHCP server configured), assign one:

    sudo ip addr add 10.100.0.1/24 dev poe0
    sudo ip link set poe0 up
    
  2. Configure your camera with a static IP in that same subnet (e.g., if poe0 is 10.100.0.1/24, set the camera to 10.100.0.100).

  3. Test: ping 10.100.0.100

Bridge to main network (flat “switch mode”):

By default exaviz-netplan puts each PoE port on its own /24 subnet with a small local DHCP server: dnsmasq, configured per port in /etc/dnsmasq.d/00-exaviz-dhcp-server-interfaces.conf from the ports you selected at install time (rerun sudo dpkg-reconfigure exaviz-netplan to change the selection). A camera on poe1 gets 10.100.1.x, poe2 gets 10.100.2.x, and so on. That isolates each camera, but it also means the cameras are not on your main LAN, do not get addresses from your router, and (because the board does not route or NAT between those per-port subnets and the WAN) cannot reach the internet for NTP or updates.

There is no “switch mode” toggle; you build a flat layout yourself by bridging all the PoE ports together with the WAN uplink, so the Cruiser and every camera sit on one network served by your upstream router’s DHCP, like an ordinary unmanaged switch.

A quick map of the interfaces (they form a small internal switch tree, so the names look unusual):

InterfaceWhat it is
eth12.5 GbE WAN port, your uplink to the router (RTL8156BG, USB)
poe0-poe7The front-panel PoE / switch ports (cameras plug in here)
eth0The CM5’s internal link to the switch (the DSA conduit / CPU port, not a front port)
ext0_1, ext0_2Internal links between the switch chips (not front ports)

Only eth1 and poe0-poe7 go in the bridge. Leave eth0, ext0_1, and ext0_2 alone; they are the internal plumbing that has to stay up for the switch to work.

Run these commands (Raspberry Pi OS / Debian):

# 1. Turn off the per-port DHCP servers (dnsmasq)
sudo systemctl disable --now dnsmasq

# 2. Remove the per-port connections and the standalone WAN connection so they
#    do not fight the bridge. List them first to confirm the names on your box:
nmcli -t -f NAME,DEVICE con show | grep -E '(poe[0-7]|eth[01]):'
for i in $(seq 0 7); do sudo nmcli con delete "netplan-poe$i" 2>/dev/null; done
sudo nmcli con delete netplan-wan-cruiser 2>/dev/null   # the eth1 / WAN connection

# 3. Create the bridge and add the WAN uplink + all PoE ports.
#    autoconnect-priority keeps the bridge ports from being grabbed by the
#    generic conduit connection at boot. (On a 4-port Lite/Keel, use poe0..poe3.)
sudo nmcli con add type bridge con-name br0 ifname br0 \
     bridge.stp no ipv4.method auto ipv6.method ignore
for i in eth1 poe0 poe1 poe2 poe3 poe4 poe5 poe6 poe7; do
  sudo nmcli con add type ethernet con-name "br0-$i" ifname "$i" master br0 \
       connection.autoconnect-priority 100
done
sudo nmcli con up br0

bridge.stp no disables spanning-tree, which is fine for cameras and end devices; leave it off unless you are chaining switches in a way that could form a loop.

br0 now requests an address from your router, and every camera on a PoE port does too. Verify:

ip -br addr show br0    # br0 should hold an address on your router's subnet
nmcli device status     # eth1 + poe0..7 show "connected" with master br0

To return to the default per-port layout, delete the br0* connections (nmcli con delete), re-enable dnsmasq, and run sudo dpkg-reconfigure exaviz-netplan.

Ubuntu (systemd-networkd)

On Ubuntu images the Netplan back end is systemd-networkd, not NetworkManager, so a hand-written bridges: stanza in /etc/netplan/ does persist across reboots (the Debian rewrite problem above does not apply). The result is the same flat layout, verified on Ubuntu 26.04.

A few Ubuntu-specific details, all confirmed in the field:

  • The WAN port is named wan (not eth1) once exaviz-netplan is installed. Confirm your names with ip -br link before you start.
  • 00-exaviz-wan.yaml runs DHCP on wan, which conflicts with wan becoming a bridge member. Retire that file (or disable its dhcp4) as part of the switch.
  • Your Wi-Fi password lives in 50-cloud-init.yaml, which this procedure removes. If Wi-Fi is your way back in during the change, migrate it first (below) or you will cut off your own lifeline.
# 1. FIRST: move Wi-Fi into its own file so removing 50-cloud-init.yaml later
#    does not take your Wi-Fi (and your lifeline) with it. Put your SSID + PSK here.
#    (wlan0 is the CM5's built-in Wi-Fi; confirm your interface name with `ip -br link`.)
sudo tee /etc/netplan/90-wifi.yaml >/dev/null <<'EOF'
network:
  version: 2
  renderer: networkd
  wifis:
    wlan0:
      access-points:
        "YOUR_SSID": {password: "YOUR_PASSPHRASE"}
      dhcp4: yes
      optional: true
EOF
sudo chmod 600 /etc/netplan/90-wifi.yaml
sudo netplan apply           # confirm Wi-Fi is still connected before continuing

# 2. Back up your current network config (so you can revert):
sudo cp -a /etc/netplan /root/netplan.bak

# 3. Stop the per-port DHCP and retire the files that fight the bridge:
sudo systemctl disable --now dnsmasq
sudo rm -f /etc/netplan/01-exaviz-dhcp-server-interfaces.yaml
sudo rm -f /etc/netplan/00-exaviz-wan.yaml      # its DHCP-on-wan conflicts with bridging
# take networking over from cloud-init, then remove its file (Wi-Fi is safe in 90-wifi.yaml now):
echo 'network: {config: disabled}' | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
sudo rm -f /etc/netplan/50-cloud-init.yaml

# 4. Create the bridge (WAN + all PoE ports; leave eth0/ext0_1/ext0_2 out).
#    On a 4-port Lite/Keel, delete the poe4-poe7 lines in BOTH the ethernets:
#    block AND the bridge interfaces: list below (a stale member leaves br0 degraded).
sudo tee /etc/netplan/01-exaviz-switch-mode.yaml >/dev/null <<'EOF'
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:   {dhcp4: no, dhcp6: no, optional: true}
    ext0_1: {dhcp4: no, dhcp6: no, optional: true}
    ext0_2: {dhcp4: no, dhcp6: no, optional: true}
    wan:    {dhcp4: no, dhcp6: no, optional: true}
    poe0: {dhcp4: no, optional: true}
    poe1: {dhcp4: no, optional: true}
    poe2: {dhcp4: no, optional: true}
    poe3: {dhcp4: no, optional: true}
    poe4: {dhcp4: no, optional: true}
    poe5: {dhcp4: no, optional: true}
    poe6: {dhcp4: no, optional: true}
    poe7: {dhcp4: no, optional: true}
  bridges:
    br0:
      interfaces: [poe0,poe1,poe2,poe3,poe4,poe5,poe6,poe7,wan]
      dhcp4: yes
      dhcp6: no
      optional: true
      mtu: 1500
      parameters: {stp: false, forward-delay: 0}
EOF
sudo chmod 600 /etc/netplan/01-exaviz-switch-mode.yaml

# 5. Validate (no live change), then apply:
sudo netplan generate
sudo netplan apply

br0 now takes one address from your router, and every camera on a PoE port does too. Verify with ip -br addr show br0.

Same caveats as the Debian recipe: keep device MTU at or below 1500 (the internal switch tagging caps the path), existing cameras keep their old per-port lease until they power-cycle, and if any integration reaches the board by IP (for example an MQTT PoE bridge), re-point it at the bridge’s new address. In switch mode the Home Assistant PoE plugin needs the switch-mode-aware release to identify devices on a port (neighbours attach to br0, not to poeN).

To revert to the default per-port layout, run this from the console (restoring the backup alone is not enough: the switch-mode file was created after the backup, and dnsmasq was disabled):

sudo rm -f /etc/netplan/01-exaviz-switch-mode.yaml /etc/netplan/90-wifi.yaml \
           /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
sudo cp -a /root/netplan.bak/. /etc/netplan/     # brings back 50-cloud-init.yaml, 00-exaviz-wan.yaml, per-port files
sudo systemctl enable --now dnsmasq              # re-enable per-port DHCP
sudo netplan apply

WiFi Setup

The Cruiser can use WiFi from two sources:

  1. CM5 built-in WiFi (if your CM5 module includes WiFi)
  2. ESP32-C6 module WiFi - shipping as the factory default firmware (see note below)

Using CM5 Built-in WiFi

For compute modules with built-in WiFi (CM5 with wireless), configure WiFi using wpa_supplicant:

# Create WiFi configuration
wpa_passphrase "YourNetworkName" "YourPassword" | \
    sudo tee /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

# Enable WiFi at boot
sudo systemctl enable wpa_supplicant@wlan0
sudo systemctl start wpa_supplicant@wlan0

Restart networking:

sudo systemctl restart wpa_supplicant@wlan0

ESP32-C6 WiFi

For full ESP32 configuration details and how to request the Zigbee firmware, see the ESP32 Wireless Module page.

PoE Port Management

Checking PoE Status

head -20 /dev/pse

Example output (streams continuous data):

0-0: power-on 0 15.50 47.8750 0.05250/0.80000 34.0625/150.0000
0-1: detecting ? 0.00 47.8750 0.00000/0.80000 35.5625/150.0000
0-2: detecting ? 0.00 47.8750 0.00000/0.80000 36.4375/150.0000
...

Using PoE Tool (GUI)

Install the exaviz-poe-tool package for a graphical PoE management interface:

sudo apt install exaviz-poe-tool

Using PoE Tool from a terminal

The same package also installs exaviz-poe-tui, which does everything the desktop app does without needing a desktop. It is a single static binary, so on a Lite image you can skip the GTK libraries entirely:

sudo apt install --no-install-recommends exaviz-poe-tool

Run it with no arguments for an interactive terminal UI:

sudo exaviz-poe-tui

Inside the UI, press h or ? for help. Arrow keys or j/k select a row, e enables the selected port, x disables it (asking first), r power cycles it, a and t force af or at mode, and q quits.

One-off commands

Every action is also available as a subcommand, so you do not need the UI:

exaviz-poe-tui status              # one line per port
exaviz-poe-tui status --json       # machine-readable, for scripts
sudo exaviz-poe-tui up poe3        # enable a port
sudo exaviz-poe-tui down poe3      # disable a port
sudo exaviz-poe-tui reset poe3     # power cycle a port
sudo exaviz-poe-tui mode poe3 af   # force the class budget to af, or at

Add --dry-run to any action to print what it would send without sending it. That is worth using whenever a script picks the port, so you can see which port the name resolved to before anything is switched.

Port names

Two forms are accepted. 0-3 means controller 0, port 3, and is always unambiguous. poe3 is the OS interface name, and is accepted only when telemetry is readable, because ports-per-controller differs between products: poe7 is 1-3 on a Cruiser and 0-7 on an Interceptor. It is resolved from what the board actually reports rather than assumed.

Writing scripts against it

Parse the --json output rather than the columns. The plain text is written for people to read and may be reformatted; the JSON is the stable contract.

The exit codes are meant to be checked:

CodeMeaning
0Success
1Operational failure: no device, write refused, permission denied
2Usage error: unknown command, bad port, missing argument
3Device busy, another process is reading it. Retryable
4Timed out waiting for telemetry

Code 3 is deliberate. The telemetry device takes a single reader, and two readers garble each other, so status refuses rather than print values it cannot trust. If the desktop app or the management service is already reading the device, the terminal tool tells you so instead of showing you nonsense.

Writing to a port needs access to the telemetry device, so run under sudo or add your user to the dialout group. Disabling a port is recorded to syslog, so a cron job that cuts power leaves a trace even if its output is discarded.

PoE Port Status Values

StatusMeaning
power-onDevice detected and receiving power
detectingPort enabled, looking for device
disabledPort administratively disabled
faultError condition
backoffTemporary backoff after detection failure

Customizing Port Names

By default, the /dev/pse output shows ports using their physical controller-port identifiers (e.g., 0-0, 0-1, 1-0). The exaviz-dkms package configures friendly names like poe0, poe1, etc. during installation based on your board model.

You can customize these names to match physical labels on your enclosure or identify connected devices (e.g., camera1, doorbell).

Run the package reconfiguration with low priority to access the port naming option:

sudo dpkg-reconfigure -plow exaviz-dkms

The -plow flag shows the low-priority port naming question, which is not displayed during normal installation. You’ll be prompted to enter a comma-separated list of port names.

Method 2: Manual config.txt Editing

For automation or scripting, you can directly edit /boot/firmware/config.txt and add port name parameters to the dtoverlay line:

dtoverlay=cruiser-raspberrypi-cm5,p1_0_name=poe0,p1_1_name=poe1,p1_2_name=poe2,p1_3_name=poe3,p0_0_name=poe4,p0_1_name=poe5,p0_2_name=poe6,p0_3_name=poe7

Port Parameter Reference

The Cruiser has up to three network switches. Port parameters follow the format pX_Y_name where X is the switch number and Y is the port on that switch.

ParameterPhysical LocationDefault Name (Cruiser)
p1_0_name - p1_3_nameSwitch 1 (leftmost, 4 ports)poe0 - poe3
p0_0_name - p0_3_nameSwitch 0 (middle, 4 ports)poe4 - poe7
p2_0_name - p2_7_nameSwitch 2 (expansion, 8 ports)poe8 - poe15

Model-Specific Defaults

Each Cruiser model has different default port configurations:

ModelDefault Port Names
Cruiser (8 built-in + 8 expansion)poe0 - poe15
Cruiser Lite (4 built-in + 8 expansion)poe0 - poe11
Cruiser Keel (4 switch + 8 expansion)swp0 - swp3, poe0 - poe7

Storage Setup

NVMe Configuration

NVMe drives are automatically detected as /dev/nvme0n1.

Check NVMe status:

# List NVMe devices
nvme list

# View detailed info
nvme smart-log /dev/nvme0n1

SATA Configuration

SATA drives appear as /dev/sda and /dev/sdb.

# List block devices
lsblk

# View SATA controller
lsusb | grep JMS

Hardware RAID (DIP Switch)

The JMS561 controller supports hardware RAID via DIP switch S3 and the RAID Initialize button (S2).

See Hardware Interface - RAID DIP Switch for switch positions and the step-by-step procedure.

JMicron RAID Manager (raidmgr_static)

The JMicron raidmgr_static tool is essential for RAID management:

  • Only way to delete a RAID array — DIP switches can only create arrays, not delete them
  • Only way to view array status — check current RAID mode, drive health, and capacity
  • Configure RAID without power cycling — create RAID 0, RAID 1, or JBOD via software

SPAN mode requires hardware DIP switches and cannot be created via this tool.

Download: raidmgr_static_cloudshell2.zip (from ODROID wiki)

After downloading, extract and install on the Cruiser:

unzip raidmgr_static_cloudshell2.zip
sudo install -m 755 raidmgr_static /usr/sbin/
sudo raidmgr_static

Common commands:

CommandDescription
GCGet available controllers
DC C0Display controller 0 info
SS C0Show SATA drive info
SR C0Show RAID status
SF C0Show firmware version
CR C0 D0,1 R0Create RAID 0 with disks 0 and 1
CR C0 D0,1 R1Create RAID 1 with disks 0 and 1
CR C0 D0,1 JBODCreate JBOD (combined volume)
DR C0 R0Delete RAID array 0
EXExit

Example: Detect controller and show info

JMS56X> GC
 --> Total available JMS56X controllers = 1 <--

JMS56X> DC C0
Controller[0]
-- ChipID       = 10
-- SerialNumber = 427491329
-- Sata[0]
------ ModelName    = WDC WD22PURZ-74B4ZY0
------ SerialNumber =      WD-WX12D14845V6
------ FirmwareVer  = 80.00A80
------ Capacity     = 1863 GB
------ PortType     = Hard Disk
------ PortSpeed    = Gen 3
-- Sata[1]
------ ModelName    = WDC WD22PURZ-74B4ZY0
------ SerialNumber =      WD-WX12D1484DLY
------ FirmwareVer  = 80.00A80
------ Capacity     = 1863 GB
------ PortType     = Hard Disk
------ PortSpeed    = Gen 3

JMS56X> SF C0
Firmware Version = V9E.01.00.04

Example: Create RAID 0 and verify

JMS56X> CR C0 D0,1 R0
JMS56X> SR C0
-- Raid[0]
------ ModelName       = S/W RAID0
------ Capacity        = 3725 GB
------ RaidStatus      = Normal
------ RaidLevel       = RAID 0
------ RaidMbrCount    = 2

Linux Software RAID (mdadm)

As an alternative to hardware RAID, you can use Linux software RAID (mdadm). This bypasses the JMS561 controller’s RAID features entirely.

Hardware vs Software RAID (2-Drive Comparison)

FeatureHardware (JMS561)Software (mdadm)
RAID Levels0, 1, JBOD, SPAN0, 1
Survives OS reinstallYesNo (must reassemble)
Monitoringraidmgr_static onlymdmonitor, email alerts
CPU usage~0%3-5% during I/O
Random write IOPSBaseline5.5x better (RAID 0)
Sequential throughput~315 MiB/s~310 MiB/s (same)
MaturityProprietary firmwareDecades of production use
PortabilityNeeds same controllerWorks on any Linux
Setup complexityDIP switchesMore Linux knowledge

Choose hardware RAID if:

  • You want zero CPU overhead
  • Simple setup that survives OS reinstalls
  • You need SPAN mode (hardware only)
  • You’re not comfortable with Linux administration

Choose software RAID (mdadm) if:

  • You need good random I/O performance (databases, VMs)
  • You want failure alerts via email
  • You may need to recover data on a different system
  • You plan to expand storage later

mdadm Example

# Install mdadm
sudo apt install mdadm

# Create partitions on each drive (use full disk)
sudo parted /dev/sda mklabel gpt
sudo parted /dev/sda mkpart primary 0% 100%
sudo parted /dev/sdb mklabel gpt
sudo parted /dev/sdb mkpart primary 0% 100%

# Create RAID 1 array using partitions (not raw devices)
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1

# Save configuration (important for boot)
sudo mdadm --detail --scan >> /etc/mdadm/mdadm.conf
sudo update-initramfs -u

# Format and mount
sudo mkfs.ext4 /dev/md0
sudo mount /dev/md0 /mnt/storage

PCIe Gen 3 (Unofficial)

CM5 unofficially supports PCIe Gen 3 for faster NVMe performance.

Edit /boot/firmware/config.txt:

dtparam=pciex1_gen=3

Reboot and verify:

# Check link speed
sudo lspci -vv | grep -i lnksta

Smart Home Integration

The Cruiser’s built-in ESP32-C6 module can act as a Zigbee coordinator without external USB dongles.

Fan Control

PWM Fan (J19)

The 4-pin CPU fan supports PWM control:

# Check fan speed
cat /sys/class/hwmon/hwmon*/fan1_input

# Set PWM (0-255)
echo 128 | sudo tee /sys/class/hwmon/hwmon*/pwm1

3-Pin Fans (J20, J21)

3-pin fans run at full speed (12V). No software control available.

Troubleshooting

Board Won’t Power On

  1. Verify power supply meets minimum voltage for your model:
    • Cruiser/Cruiser Lite: 48V minimum
    • Cruiser Keel: 13V minimum (see Power Calculator for details)
  2. Check D2 (blue standby LED) — should be lit
  3. Press S0 (power button) or external power button
  4. Check for shorts on the CM5 module

No PoE Power

  1. Verify input voltage is 48V (required for PoE+)
  2. Check /dev/pse for port status
  3. Verify PoE device is 802.3af/at compliant
  4. Check total power budget isn’t exceeded

NVMe Not Detected

  1. Verify NVMe is properly seated in M.2 slot
  2. Check dmesg | grep nvme for errors
  3. Try a different NVMe drive
  4. Ensure M.2 screw is securing the drive

WiFi Issues

See ESP32 Troubleshooting for WiFi, Bluetooth, and Zigbee issues.

WAN Port Green LED Not Working

The green WAN LED (1 GbE / 2.5 GbE indication) requires the exaviz-netplan package. Install or update it and the green LED enables automatically:

sudo apt update && sudo apt install --only-upgrade exaviz-netplan

The amber LED (10/100 Mbps and 1 GbE) works without any Exaviz software. On a stock operating system the green LED stays off by design.

Last modified October 11, 2026