OCI container with libguestfs, qemu and image manipulation tools (Podman-first)
Explore the docs »
Report Bug
·
Request Feature
Table of Contents
This project provides an OCI container image containing libguestfs, qemu, and other essential tools for virtual machine image manipulation. Based on Rocky Linux 10 UBI, this container is optimized for size and performance.
The image is built with Buildah and run with Podman (rootless-friendly, no daemon). Any OCI-compatible engine works at runtime, but all examples in this repo use podman.
The image is published in two variants. Pick by tag:
| Tag | Contents | Architectures | Use case |
|---|---|---|---|
:latest, :slim |
libguestfs + qemu + Linux filesystem tools (ext/xfs/btrfs/fat) + parted/gdisk + cloud-utils | amd64 + arm64 | Default. Building and customizing Linux VM images (virt-customize, virt-sysprep, virt-sparsify). Powers the openimages.cloud build pipeline. |
:full |
Everything in :slim plus virt-v2v and ntfs-3g |
amd64 only* | VMware/Hyper-V → KVM conversions, Windows guest manipulation |
* virt-v2v is not packaged for aarch64 on EPEL 10 (it converts VMs from x86 hypervisors), so the :full variant is published amd64-only.
Both variants are signed via cosign keyless (Sigstore) and ship with an SPDX SBOM attestation.
- Ready-to-use libguestfs with
directbackend (no libvirtd required) - Linux filesystems out of the box: ext2/3/4, XFS, BTRFS, FAT32 (NTFS only in
:full) qemu-kvm-core(no graphical/audio subpackages) — minimal qemu surface- Pre-tuned env vars for libguestfs appliance memory & CPU
- Provenance: OCI labels (revision, version, created, source), Cosign signature, SPDX SBOM
The image is signed keyless via GitHub OIDC. To verify before pulling:
cosign verify ghcr.io/stackopshq/libguestfs-tools:latest \
--certificate-identity-regexp '^https://github.com/stackopshq/libguestfs-tools-container/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comThe SBOM is attached as a cosign attestation:
cosign download attestation ghcr.io/stackopshq/libguestfs-tools:latest \
--predicate-type https://spdx.dev/Document- Podman 4.0 or later installed on your system
- Sufficient disk space for your VM images
- Basic knowledge of libguestfs tools
- For advanced operations: ability to run containers with
--privileged - Optional:
/dev/kvmaccess for better performance with nested virtualization
SELinux note: on Enforcing hosts (RHEL/Rocky/Fedora), append
:Zto bind-mount sources (e.g.-v ./images:/workspace/images:Z) so Podman relabels the volume for the container. Without this you'll hit permission denied errors.
Pull the image from GitHub Container Registry:
podman pull ghcr.io/stackopshq/libguestfs-tools:latest # slim (default)
podman pull ghcr.io/stackopshq/libguestfs-tools:full # with virt-v2v + ntfs-3g
podman pull ghcr.io/stackopshq/libguestfs-tools:v2 # pinned major (slim)
podman pull ghcr.io/stackopshq/libguestfs-tools:v2.0.0-full # pinned fullTo build the image yourself:
git clone https://github.com/stackopshq/libguestfs-tools-container.git
cd libguestfs-tools-container
# Slim (default)
podman build -t libguestfs-tools:local .
# Full (with virt-v2v + ntfs-3g)
podman build --build-arg VARIANT=full -t libguestfs-tools:local-full .A compose.yml file is provided for easier container management. With podman-compose:
podman-compose run --rm libguestfs-tools bashOr run specific commands:
podman-compose run --rm libguestfs-tools virt-df -a /workspace/images/my-vm.qcow2-
Mount a volume to share images with the container
podman run --rm -v /local/path/images:/workspace/images:Z \ ghcr.io/stackopshq/libguestfs-tools \ virt-df -a /workspace/images/my-vm.qcow2
-
Run libguestfs tools interactively
podman run --rm -it -v /local/path/images:/workspace/images:Z \ ghcr.io/stackopshq/libguestfs-tools bash
-
Execute specific commands
podman run --rm -v /local/path/images:/workspace/images:Z \ ghcr.io/stackopshq/libguestfs-tools \ virt-customize -a /workspace/images/my-vm.qcow2 --install nginx
podman run --rm -v /local/path/images:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-tools:full \
virt-v2v -i ova /workspace/images/source-vm.ova -o local -os /workspace/images -of qcow2podman run --rm -v /local/path/images:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-tools \
virt-inspector /workspace/images/my-vm.qcow2podman run --rm -v /local/path/images:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-tools \
qemu-img resize /workspace/images/my-vm.qcow2 +10Gpodman run --rm -it --privileged -v /local/path/images:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-tools \
guestmount -a /workspace/images/my-vm.qcow2 -m /dev/sda1 /mntThe examples/ directory contains ready-to-use shell scripts for common operations:
- convert-vmdk-to-qcow2.sh - Convert VMware images to QCOW2 format
- inspect-vm-image.sh - Inspect VM images for OS and application details
- customize-vm.sh - Customize VM images by installing packages
See the examples/README.md for detailed usage instructions.
The container is configured with the following environment variables for libguestfs:
| Variable | Default Value | Description |
|---|---|---|
LIBGUESTFS_BACKEND |
direct |
Uses direct backend (no nested VM) |
LIBGUESTFS_DEBUG |
0 |
Set to 1 to enable debug output |
LIBGUESTFS_TRACE |
0 |
Set to 1 to enable function tracing |
LIBGUESTFS_PROGRESS |
1 |
Shows progress bars during operations |
LIBGUESTFS_VERBOSE |
0 |
Set to 1 for verbose output |
LIBGUESTFS_MEMSIZE |
4096 |
Memory size in MB for libguestfs appliance |
LIBGUESTFS_SMP |
4 |
Number of virtual CPUs for libguestfs appliance |
You can override these values when running the container:
podman run --rm -e LIBGUESTFS_VERBOSE=1 -e LIBGUESTFS_DEBUG=1 \
-v /local/path:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-tools- qcow2, raw, VMDK, VDI, VHD/VHDX (handled natively by
qemu-img) - OVA / OVF —
:fullonly (requiresvirt-v2v)
- qcow2 (recommended for KVM/OpenStack — sparse, snapshots, compression)
- raw (fastest, largest)
- VMDK (for VMware compat)
- VDI (for VirtualBox compat)
:slim(default) — Linux: ext2/3/4, XFS, BTRFS · FAT32 · ISO9660/UDF:full— adds NTFS (read/write) for Windows guests viantfs-3g
Permission denied on bind mounts (SELinux):
The host is running SELinux in Enforcing mode. Append :Z to the volume so Podman relabels it for the container, e.g. -v ./images:/workspace/images:Z. Never disable SELinux as a workaround.
Permission denied for privileged operations:
# Run with --privileged for guestmount, direct device access, etc.
podman run --rm --privileged -v /local/path:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-toolsEnable verbose output for debugging:
podman run --rm -e LIBGUESTFS_VERBOSE=1 -e LIBGUESTFS_DEBUG=1 \
-v /local/path:/workspace/images:Z \
ghcr.io/stackopshq/libguestfs-toolsContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Don't forget to give the project a star! ⭐ Thanks again!
Distributed under the GPL-3.0 License. See LICENSE for more information.
Kevin Allioli
- Twitter: @stackopshq
- Email: [email protected]
- LinkedIn: kevinallioli
Project Links:
- Repository: https://github.com/stackopshq/libguestfs-tools-container
- Issues: Report a Bug
- Container Registry: ghcr.io/stackopshq/libguestfs-tools