| name | linux-virtualization |
| description | Use when operating KVM/libvirt virtual machines or LXD system containers, including lifecycle, snapshots, backups, storage, networking, and host inspection. Use linux-container-engine and linux-container-deployment for Docker or Podman application containers. |
| license | MIT |
| metadata | {"portable":true,"compatible_with":["claude-code","codex"],"author":"Peter Bamuhigire","author_url":"techguypeter.com","author_contact":"+256784464178"} |
Linux Virtualization
Distro support
Two-family skill. KVM/libvirt (virsh, virt-install) is portable across both
families; LXD system containers are Ubuntu-centric (Canonical/snap) with no
native LXD on RHEL. Body uses Debian/Ubuntu; substitute per this matrix.
Application containers (Docker/Podman) moved out of this skill. For the
container engine, running containers, and image cleanup, use the
12-containers-and-orchestration skills: linux-container-engine
(install/configure Docker & Podman), linux-container-deployment
(run containers, compose, systemd/Quadlet), and linux-image-hygiene
(prune images/volumes). This skill keeps KVM/libvirt VMs and LXD system
containers only.
| Concept | Debian/Ubuntu | RHEL family |
|---|
| System containers | LXD (snap) | systemd-nspawn (no native LXD); Podman for app containers |
| VMs (KVM) | qemu-kvm, libvirt-daemon-system | qemu-kvm, libvirt |
| Manage VMs | virsh, virt-install | identical |
| VM/container firewall | ufw (known quirks) | firewalld + nftables |
| LXD volume labeling | n/a | SELinux: mount with :z/:Z for host-shared storage |
RHEL-family notes: LXD is Ubuntu-centric and not native on RHEL — on the
RHEL family use systemd-nspawn for system containers and Podman for
application containers (see linux-container-engine). KVM/libvirt is identical
across families. SELinux relabels bind-mounted host storage — append :z
(shared) or :Z (private). See
../../07-security-and-hardening/linux-server-hardening/references/selinux-reference.md
and ../../docs/multi-distro/plan.md.
Use when
- Managing LXD system containers or KVM/libvirt VMs on a host.
- Investigating VM or LXD-container lifecycle failures.
- Taking snapshots or backups before risky changes.
Do not use when
- The task is application containers (Docker/Podman, compose, image cleanup); use the
12-containers-and-orchestration skills (linux-container-engine, linux-container-deployment, linux-image-hygiene).
- The task is configuration management for the host itself; use
linux-config-management.
- The task is ordinary application service management outside the VM/LXD layer.
Required inputs
| Artefact | Source | Required? | If absent |
|---|
| Host family, hypervisor/container layer, target identity, and desired lifecycle outcome | Operator and host inventory | required | Discover read-only; do not act on an ambiguous name. |
| Current guest definition, storage/network attachments, state, and host capacity | libvirt/LXD host | required for mutation | Return a preflight report only. |
| Backup/snapshot policy, downtime window, recovery target, and change authority | Workload owner | required for destructive or disruptive action | Stop before mutation. |
Workflow
- Identify the owning virtualization layer and target workload.
- Inspect current state before changing it.
- Apply the matching workflow below for lifecycle, snapshot, backup, or startup diagnosis.
- Verify the guest or container state and host-level impact after the action.
- Stop if the target, storage/network ownership, capacity, backup consistency, rollback, downtime, or action authority is unresolved.
- Recover by reverting the recorded definition/snapshot or restoring the independent backup, then verify both guest state and workload health.
Quality standards
- Keep host and guest responsibilities distinct.
- Snapshot or back up before risky mutations when possible.
- Validate both orchestration state and actual workload health.
Anti-patterns
- Treating LXD system containers and Docker/Podman application containers as interchangeable. Fix: route application containers to category 12.
- Deleting a guest, disk, snapshot, or image before proving ownership. Fix: inventory attachments, dependants, backup, and retention first.
- Debugging only inside the guest. Fix: inspect host capacity, libvirt/LXD state, storage, networking, and logs.
- Calling a snapshot a backup. Fix: export or copy recovery data to an independent failure domain and test restore metadata.
- Starting a migration or resize without capacity/downtime checks. Fix: preflight destination compatibility and define rollback.
Outputs
| Artefact | Consumer | Acceptance condition |
|---|
| Guest diagnosis or lifecycle action | Virtualisation operator | Correct target/layer is identified and host plus guest state match the requested outcome. |
| Snapshot/backup/recovery record | Workload owner | Artifact location, consistency method, retention, restore command, and verification are recorded. |
| Capacity and impact evidence | Infrastructure owner | CPU, memory, storage, network attachments, downtime, and rollback are checked before change. |
References
references/lxd-reference.md
- For Docker/Podman application containers:
linux-container-engine, linux-container-deployment, and linux-image-hygiene in 12-containers-and-orchestration.
Evidence Produced
| Artefact | Acceptance condition |
|---|
| Virtualisation evidence | Includes target definition, host capacity, attachments, state/logs, backup or snapshot identity/location, lifecycle result, and workload health. |
Capability contract
Inspection defaults to read-only. Read/execute access to the host is required. Start/stop, snapshot, backup, resize, migration, XML/profile edits, storage/network changes, or deletion require explicit authority. Deletion and overwrite require named target verification and a recoverable backup.
Degraded mode
Without host or guest access, review supplied definitions/logs and mark capacity, storage consistency, runtime, and workload health not assessed. Without a verified backup or recovery path, stop before destructive or irreversible work.
Decision rules
| Choice | Action | Failure or risk avoided |
|---|
| Full OS isolation/legacy kernel workload | Use KVM/libvirt | Container-host coupling. |
| Lightweight system container on supported Ubuntu host | Use LXD | Unneeded VM overhead. |
| Packaged application container | Route to category 12 | Competing lifecycle tools. |
Worked example
Before changing a production libvirt VM, identify its disks and networks, check host capacity, create an application-consistent backup to independent storage, record restore steps, take a short-lived snapshot, apply the approved change, verify guest and application health, then remove the snapshot only after the retention gate.
This skill is self-contained. Every command below uses standard tools
(lxc, virsh); the body shows Debian/Ubuntu, with RHEL-family substitutions
(SELinux :z/:Z) per the Distro support matrix above. The sk-* scripts
in the Optional fast path section are convenience wrappers — never required.
This skill owns the VM and system-container layer on a host: LXD system
containers (Canonical's native, Ubuntu-centric) and KVM/libvirt for full
virtual machines.
It does not own:
- Application containers (Docker/Podman), compose, and image cleanup — use
the
12-containers-and-orchestration skills: linux-container-engine,
linux-container-deployment, linux-image-hygiene.
- Kubernetes — out of scope for v1.
- Cloud provider VMs (EC2, DigitalOcean droplets) — managed at the
provider side.
- Applications inside containers — managed by application-specific
skills.
Informed by the Canonical Ubuntu Server Guide (LXD, KVM chapters).
When to use
- Listing LXD containers and VMs on a host.
- Creating or restoring LXD container snapshots.
- Exporting/backing up an LXD container or VM to a tar file.
- Debugging why an LXD container or VM won't start.
When NOT to use
- Running or deploying Docker/Podman application containers — use
linux-container-deployment (engine setup: linux-container-engine).
- Deploying a web application inside a container — use
linux-site-deployment.
- Host firewall rules — use
linux-firewall-ssl.
- Kubernetes/Nomad orchestration — out of scope.
Standing rules
- LXD over legacy LXC.
lxc (the LXD CLI) is the modern, declarative
wrapper. Direct lxc-* (legacy) commands are discouraged.
- Always snapshot before mutating. Snapshot → mutate → verify. Roll
back on failure.
- Snapshots are not backups. They live on the same pool. Export
containers/VMs to tar on separate storage for real backup.
- Resource limits are mandatory in production. Unbounded containers
eat the host. Set
limits.memory, limits.cpu, and limits.disk in
every profile.
- Privileged containers are banned unless justified in writing.
Unprivileged is the default.
Quick reference — manual commands
LXD
lxc list
lxc list -f compact
lxc info <name>
lxc launch ubuntu:24.04 web01
lxc exec web01 -- bash
lxc stop web01
lxc start web01
lxc delete web01 --force
lxc snapshot web01 before-upgrade-2026-04-10
lxc info web01 | grep -A10 Snapshots
lxc restore web01 before-upgrade-2026-04-10
lxc delete web01/before-upgrade-2026-04-10
lxc export web01 /backups/lxd/web01-$(date +%Y%m%d).tar.gz
lxc import /backups/lxd/web01-20260410.tar.gz
lxc config set web01 limits.memory 1GB
lxc config set web01 limits.cpu 2
lxc config device override web01 root size=10GB
lxc remote add remotehost <ip>
lxc copy web01 remotehost:web01-copy
Full LXD reference (lxd init, profiles, storage backends, networks,
cloud-init integration, 6 worked examples) — see
references/lxd-reference.md.
Docker / Podman application containers are no longer covered here. Use the
12-containers-and-orchestration skills: linux-container-engine,
linux-container-deployment, and linux-image-hygiene.
KVM / libvirt
sudo virsh list --all
sudo virsh dominfo <vm>
sudo virsh start <vm>
sudo virsh shutdown <vm>
sudo virsh destroy <vm>
sudo virsh snapshot-create-as <vm> snap-before-upgrade
sudo virsh snapshot-list <vm>
sudo virsh snapshot-revert <vm> snap-before-upgrade
Typical workflows
Workflow: "What's running on this host?"
echo "=== LXD ==="
lxc list 2>/dev/null || echo "(lxd not installed)"
echo
echo "=== KVM ==="
sudo virsh list --all 2>/dev/null || echo "(libvirt not installed)"
(For Docker/Podman containers on the host, use sk-container-ps from
linux-container-deployment.)
Workflow: "Snapshot before I mess with it"
lxc snapshot web-prod before-upgrade-$(date +%Y%m%d-%H%M)
lxc restore web-prod before-upgrade-20260410-1530
lxc delete web-prod/before-upgrade-20260410-1530
Workflow: "Back up a container to cold storage"
DEST=/backups/lxd
mkdir -p "$DEST"
lxc export web-prod "$DEST/web-prod-$(date +%Y%m%d).tar.gz"
rclone copy "$DEST/web-prod-$(date +%Y%m%d).tar.gz" gdrive:lxd-backups/
Workflow: "Why won't this LXD container start?"
lxc info web01 | grep -A10 -E 'Status|Log'
lxc info --show-log web01
lxc config show web01 | grep -E 'limits\.'
(For "why won't this Docker/Podman container start?" use
linux-container-deployment.)
Troubleshooting / gotchas
- LXD containers "lose" their IP on boot. They use DHCP from
lxdbr0
by default; if the bridge has no DHCP server, set a static IP in the
profile or container config.
- KVM VMs with bridged networking don't get IPs. Check that the host
bridge has a DHCP server on the VLAN, or configure the VM with cloud-init
static networking.
- LXD container file ownership looks weird from the host. Unprivileged
containers remap UIDs (
uid 1000 inside = uid 1001000 outside). Use
lxc file push/pull to move files without fighting ownership.
References
Optional fast path (when sk-* scripts are installed)
Running sudo install-skills-bin linux-virtualization installs:
| Task | Fast-path script |
|---|
| LXD containers with state, IP, memory, disk, uptime | sudo sk-lxd-list |
| Create / list / restore LXD snapshots | sudo sk-lxd-snapshot |
| Full LXD container export to tar | sudo sk-lxd-backup --container <n> |
These are optional wrappers. The lxc and virsh commands above are the
source of truth. For Docker/Podman, see sk-container-ps /
sk-container-prune in 12-containers-and-orchestration.
Scripts
This skill installs the following scripts to /usr/local/bin/. To install:
sudo install-skills-bin linux-virtualization
| Script | Source | Core? | Purpose |
|---|
| sk-lxd-list | scripts/sk-lxd-list.sh | no | All LXD containers with state, IPv4/IPv6, memory and disk usage, uptime. |
| sk-lxd-snapshot | scripts/sk-lxd-snapshot.sh | no | Create, list, or restore LXD container snapshots with a naming convention. |
| sk-lxd-backup | scripts/sk-lxd-backup.sh | no | Full LXD container export to tar, with restore metadata, for off-host backup. |