Skip to content

Instantly share code, notes, and snippets.

@sakti
Created September 1, 2026 06:27
Show Gist options
  • Select an option

  • Save sakti/02592fcdb298ff5d5e856bcd2a5ab66a to your computer and use it in GitHub Desktop.

Select an option

Save sakti/02592fcdb298ff5d5e856bcd2a5ab66a to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Check whether this node can run microVMs (Firecracker, Cloud Hypervisor, etc).
#
# Usage: ./check-microvm-support.sh [-q]
# -q quiet mode: no output, just exit code (0 = supported, 1 = not supported)
set -uo pipefail
QUIET=0
[[ "${1:-}" == "-q" ]] && QUIET=1
PASS=0
FAIL=0
WARN=0
log() { [[ $QUIET -eq 0 ]] && printf '%s\n' "$1"; }
ok() { PASS=$((PASS+1)); log " [OK] $1"; }
bad() { FAIL=$((FAIL+1)); log " [FAIL] $1"; }
warn() { WARN=$((WARN+1)); log " [WARN] $1"; }
section() { log ""; log "== $1 =="; }
ARCH=$(uname -m)
section "CPU virtualization extensions ($ARCH)"
case "$ARCH" in
x86_64|i686|i386)
if grep -qE '(vmx|svm)' /proc/cpuinfo 2>/dev/null; then
flag=$(grep -oE '(vmx|svm)' /proc/cpuinfo | sort -u | tr '\n' ' ')
ok "hardware virtualization present ($flag)"
else
bad "no vmx/svm flag found in /proc/cpuinfo"
fi
;;
aarch64|arm64)
# ARM: virtualization is provided by EL2/hypervisor mode, exposed via /dev/kvm.
# There's no simple /proc/cpuinfo flag equivalent to vmx/svm.
if [[ -e /sys/devices/system/cpu/cpu0 ]]; then
ok "ARM64 CPU detected; virtualization support is determined by /dev/kvm below"
else
warn "unable to inspect CPU details"
fi
;;
*)
warn "unrecognized architecture '$ARCH'; skipping CPU flag check"
;;
esac
section "KVM kernel support"
if [[ -e /dev/kvm ]]; then
ok "/dev/kvm exists"
if [[ -r /dev/kvm && -w /dev/kvm ]]; then
ok "/dev/kvm is readable/writable by current user ($(id -un))"
else
perms=$(ls -l /dev/kvm 2>/dev/null)
bad "/dev/kvm exists but is not read/write for current user ($(id -un)) -- $perms"
warn "consider: sudo usermod -aG kvm $(id -un) (then re-login)"
fi
else
bad "/dev/kvm does not exist"
fi
if command -v lsmod >/dev/null 2>&1; then
if lsmod 2>/dev/null | grep -qE '^kvm'; then
mods=$(lsmod | awk '$1 ~ /^kvm/ {print $1}' | tr '\n' ' ')
ok "KVM kernel module(s) loaded: $mods"
else
warn "no kvm* kernel module reported by lsmod (may be built-in, or unloaded)"
fi
else
warn "lsmod not available; cannot check loaded kernel modules"
fi
section "Nested / virtualized environment check"
if command -v systemd-detect-virt >/dev/null 2>&1; then
# systemd-detect-virt exits non-zero when the result is "none", so capture
# stdout separately from the exit status instead of using `|| echo fallback`.
virt=$(systemd-detect-virt 2>/dev/null)
[[ -z "$virt" ]] && virt="unknown"
if [[ "$virt" == "none" ]]; then
ok "running on bare metal (systemd-detect-virt: none)"
else
warn "running inside a virtualized environment (systemd-detect-virt: $virt) -- nested virtualization may be required"
fi
else
warn "systemd-detect-virt not found; cannot determine bare-metal vs. VM"
fi
section "Required tooling"
for bin in firecracker cloud-hypervisor; do
if command -v "$bin" >/dev/null 2>&1; then
ver=$("$bin" --version 2>/dev/null | head -n1)
ok "$bin found in PATH ($ver)"
else
warn "$bin not found in PATH"
fi
done
# Also check the local bin/ directory next to this script, common for this project layout.
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
if [[ -d "$SCRIPT_DIR" ]]; then
for f in "$SCRIPT_DIR"/firecracker* "$SCRIPT_DIR"/cloud-hypervisor*; do
[[ -f "$f" && -x "$f" ]] && ok "local binary present: $f"
done
fi
section "Summary"
log " PASS=$PASS WARN=$WARN FAIL=$FAIL"
if [[ $FAIL -eq 0 ]]; then
log ""
log "Result: this node SUPPORTS running microVMs."
exit 0
else
log ""
log "Result: this node does NOT fully support running microVMs."
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment