How to Detect Virtualization and Container Environments in Linux Using systemd-detect-virt

In modern cloud deployments, automated installation scripts, configuration management playbooks (such as Ansible or Puppet), and system maintenance routines frequently execute across diverse environments ranging from bare-metal servers to cloud hypervisors and lightweight application containers. Applying hardware-specific tuning—such as flashing disk firmware, setting CPU governor scaling, or binding physical network interfaces—inside a virtual machine or container can trigger script failures or system instability. The systemd-detect-virt command provides an instant, reliable mechanism to query CPUID registers, DMI/SMBIOS tables, and kernel namespaces, identifying whether the current system is running bare metal, under a hypervisor, or inside a container.

Understanding How systemd-detect-virt Works

Unlike fragile shell scripts that attempt to parse /proc/cpuinfo, check for specific device names, or grep lspci outputs, systemd-detect-virt implements deep hardware and kernel introspection:

  1. CPUID Leaf Checks: Queries CPU instruction set registers (such as hypervisor signature bits on x86/x86_64 architectures) to detect virtualization engines like KVM, QEMU, VMware, Microsoft Hyper-V, and Xen.
  2. DMI / SMBIOS Table Inspection: Reads motherboard and BIOS vendor strings exposed via /sys/class/dmi/id/.
  3. Container Namespace and Environment Checks: Inspects PID namespaces, control groups (cgroups), and specific filesystem signatures (such as /.dockerenv, container manager environment variables, and /proc/1/environ) to detect container platforms including Docker, Podman, LXC, systemd-nspawn, and Windows Subsystem for Linux (WSL).

The utility outputs a standardized machine-readable identifier and returns an unambiguous POSIX exit code: 0 if running in a virtual environment, and non-zero (exit code 1) if running on physical bare-metal hardware.

Detecting Any Virtualization or Container Platform

To perform an immediate check of the current operating system environment, open a terminal and execute:

systemd-detect-virt

The terminal will print the detected platform name directly to standard output:

  • kvm: Running inside a Kernel-based Virtual Machine (including Proxmox VE and AWS EC2 Nitro/KVM).
  • vmware: Running on VMware ESXi, Workstation, or Fusion.
  • oracle: Running inside Oracle VM VirtualBox.
  • microsoft: Running on Microsoft Hyper-V or Azure Virtual Machines.
  • docker: Running inside a Docker container.
  • podman: Running inside a Podman container.
  • lxc: Running inside an LXC or LXD container.
  • wsl: Running inside Windows Subsystem for Linux (WSL 1 or WSL 2).
  • none: Running directly on bare-metal physical hardware.

When running on physical hardware, systemd-detect-virt outputs none and returns exit status 1.

Distinguishing Virtual Machines from Containers

A script often needs to know specifically whether it is running inside an application container (which shares the host kernel) or inside a complete hardware virtual machine (which runs its own independent kernel).

To check exclusively for hardware virtualization (hypervisors), use the -v (or --vm) flag:

systemd-detect-virt --vm

If executed inside a container running atop a virtualized cloud instance, this command identifies the hypervisor (e.g., kvm), ignoring the container layer.

To check exclusively for container runtimes, use the -c (or --container) flag:

systemd-detect-virt --container

If executed inside a Docker or Podman container, the command outputs the container runtime (e.g., docker). If run in a standard VM without container isolation, it returns none with exit status 1.

Operating in Silent Mode for Shell Automation

In shell scripts, printing text to stdout is often unnecessary when you only need to branch execution based on the return code. The -q (or --quiet) flag suppresses all terminal output, returning only the status code.

Incorporate this concise logic into Bash scripts to prevent bare-metal utilities from running inside virtualized guests:

#!/bin/bash

if systemd-detect-virt -q; then
    VIRT_TYPE=$(systemd-detect-virt)
    echo "Running inside a virtualized environment: ${VIRT_TYPE}."
    echo "Skipping hardware fan and thermal governor adjustments."
else
    echo "Running on bare-metal hardware."
    echo "Initializing physical CPU governors and storage controller firmware checks..."
    # Apply hardware-specific tuning here
fi

Because the return code evaluates cleanly, you can write straightforward one-line assertions:

systemd-detect-virt -q && echo "Virtualized" || echo "Bare Metal"

Targeting Specific Cloud and Virtualization Environments

You can also test for specific hypervisor technologies using conditional string comparisons:

case "$(systemd-detect-virt)" in
    kvm)
        echo "Optimizing I/O scheduler for virtio-blk/virtio-scsi drivers..."
        ;;
    vmware)
        echo "Ensuring open-vm-tools service is enabled..."
        sudo systemctl enable --now open-vm-tools
        ;;
    wsl)
        echo "Detected WSL environment. Disabling systemd multi-user GUI targets."
        ;;
    none)
        echo "Bare-metal deployment verified."
        ;;
    *)
        echo "Detected generic virtualization: $(systemd-detect-virt)"
        ;;
esac

Inspecting Detailed Hardware DMI Signatures Manually

If systemd-detect-virt reports an unexpected virtualization signature or if you need to inspect raw manufacturer records, examine the sysfs DMI tree:

cat /sys/class/dmi/id/sys_vendor
cat /sys/class/dmi/id/product_name

On virtual machines, these nodes display strings such as QEMU, VMware, Inc., or Microsoft Corporation.

Integrating systemd-detect-virt into your deployment pipelines provides reliable, kernel-accurate environment detection, ensuring your automation scripts adapt intelligently across bare metal, hypervisors, and containers.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.