Convert¶
instar convert converts between disk image formats, as a drop-in
replacement for qemu-img convert.
# Convert QCOW2 to raw (flattens backing chains)
instar convert input.qcow2 output.raw
# Convert any input to QCOW2 v3 output
instar convert -O qcow2 input.raw output.qcow2
# Convert QCOW2 with backing chain to standalone QCOW2
instar convert -O qcow2 overlay.qcow2 standalone.qcow2
# Convert with compressed QCOW2 output (zlib/deflate compression)
instar convert -c -O qcow2 input.raw output.qcow2
# Convert with dense output (write all clusters including zeros)
instar convert --no-skip-zeros input.qcow2 output.raw
# Specify output cluster size for QCOW2 (512 to 2097152, default: 65536)
instar convert -O qcow2 --cluster-size 4096 input.raw output.qcow2
instar convert -O qcow2 --cluster-size 2097152 input.raw output.qcow2
# Write QCOW2 output with extended L2 entries (16-byte entries with subcluster bitmaps)
instar convert -O qcow2 --extended-l2 input.raw output.qcow2
# Write LUKS-encrypted QCOW2 output (AES-256-XTS, crypt_method=2)
instar convert -O qcow2 --luks-encrypt-passphrase 'secret' input.raw encrypted.qcow2
# Decrypt LUKS-encrypted QCOW2 back to raw
instar convert --luks-passphrase 'secret' encrypted.qcow2 output.raw
# Convert to VHD dynamic format
instar convert -O vpc input.qcow2 output.vhd
# Convert to VHDX dynamic format
instar convert -O vhdx input.qcow2 output.vhdx
# Decrypt native LUKS v2 container (Argon2id KDF)
instar convert --luks-passphrase 'secret' --max-guest-memory 1G encrypted.luks output.raw
# Decrypt LUKS container wrapping a QCOW2 image
instar convert --luks-passphrase 'secret' luks-wrapped.img output.raw
# Specify VMDK grain size (4096 to 65536, default: 65536)
instar convert -O vmdk --grain-size 4096 input.raw output.vmdk
# Specify VHD block size (524288+, default: 2097152)
instar convert -O vpc --block-size 1048576 input.raw output.vhd
# Specify VHDX block size (1048576 to 268435456, default: 33554432)
instar convert -O vhdx --block-size 4194304 input.raw output.vhdx
# Progress reporting
instar convert -p 5 input.qcow2 output.raw
The convert operation reads the virtual content of an input image (including
backing chain flattening) and writes it in the requested output format.
Compressed clusters (zlib/deflate and ZSTD) are decompressed transparently,
including clusters up to 2MB. QCOW2 v3 images with extended L2 entries
(subclusters) are also supported. Legacy AES-128-CBC encrypted QCOW2 images
(crypt_method=1) can be decrypted with --qcow2-password. LUKS-in-QCOW2
images (crypt_method=2) and native LUKS containers can be decrypted with
--luks-passphrase. LUKS v2 containers using Argon2id KDF require
--max-guest-memory (e.g., --max-guest-memory 1G). Native LUKS
containers wrapping QCOW2 images are transparently detected and
decrypted, with the inner QCOW2 processed as the conversion source.
Individual snapshots can be extracted with --snapshot <name-or-id>.
By default, convert produces sparse output by skipping zero-filled clusters
(matching qemu-img convert behavior). Use --no-skip-zeros for dense output.
The default can also be set via convert.sparse in the config file.
Supported output formats¶
- raw (default) - Flat raw output
- qcow2 - QCOW2 v3 output with 16-bit refcounts, configurable cluster
size (512 bytes to 64KB, default 64KB), optional zlib compression (
-c) - vmdk - VMDK monolithicSparse output (default), streamOptimized
with
-c, or monolithicFlat with--subformat monolithicFlat. Configurable grain size (4KB-64KB, default 64KB via--grain-size) for sparse/streamOptimized output - vpc - VHD dynamic output, configurable block size (512KB+,
default 2MB via
--block-size) - vhdx - VHDX dynamic output, configurable block size (1MB-256MB,
default 32MB via
--block-size)
Differencing images¶
A differencing VHD (footer disk type 4) or VHDX (HasParent set) stores
only the sectors that differ from a parent image. convert composes such
a source against its parent: it reads the parent's own backing chain
(following relative references beside the source, rejecting anything
outside the allowlist) and serves each sector from whichever image in the
chain actually owns it, so the output is byte-identical to the chain
flattened by hand.
If the source's own chain has no parent to read — a differencing image
with an empty or absent parent reference — convert still refuses it,
rather than composing from nothing:
convert: a differencing <VHD|VHDX> image in the chain convert was given
has no parent behind it, so the sectors it leaves to its parent could
not be composed
and exits 1 with no output file left behind. If the chain names a parent
that cannot be resolved — the file is missing, or outside the backing
file allowlist — discovery fails before any guest device is attached and
convert reports that instead, again leaving no output file.
See the "VHD/VHDX differencing" section of quirks.md for the per-operation record.