I’m trying to convert a KVM/qemu VM (i.e. a qcow2 file) to a local incus image. Maybe incus-migrate is not the right tool for this? If not, where can I find documentation on executing such a migration?The first issue is that incus-migrate can only be run as root. Why is this? I’m in the incus-admin group and so far have been able to do everything, including initialize incus as myself. It is true that I don’t have read access to /var/lib/incus and wonder why the group for this isn’t set to incus-admin rather than root by default. But that’s an aside.
Second, I’m confused by what is actually being asked for here:
Please provide the path to a root filesystem:
This makes sense if one is converting a bare metal installation to a container image, but otherwise I’m not sure what it’s asking for, given what I’m trying to do.
This is what AI told me when I asked it how do I convert a qcow2 VM to an Incus container:
To convert a qcow2 VM image into an Incus container or virtual machine, the recommended approach is to use the incus-migrate tool.
Here is the general method:
Install and use the incus-migrate tool available on Linux.
The tool can import VM images in formats including qcow2, raw, and vmdk.
Run the tool and specify the qcow2 image file as the source.
Choose to create either a container or a virtual machine instance; for a VM from qcow2, create a VM instance.
The tool copies the image data and creates an Incus instance that can be configured.
By default, the new instance uses the default profile but can be customized.
The qcow2 image will be converted to raw format internally if needed before importing.
You then start the VM instance with Incus tools like incus start and can access the console.
Details from examples show a prompt-driven flow where you specify the image path, VM options (e.g., UEFI support), and additional configurations before the import completes successfully.
Alternatively, there is a method to convert qcow2 to raw manually with qemu-img and import it as a custom storage volume, then create a VM instance using that volume as root disk, but incus-migrate is more straightforward for one-step import.
incus-migrate creates a mount tree where it places the appropriate files from the VM image file. The ability to mount requires root privileges. It likely does other things that require root.
Here is a sample run. What options did you use so that it asks you for the path to a root filesystem?
$ sudo incus-migrate
The local Incus server is the target [default=yes]: yes
What would you like to create?
1) Container
2) Virtual Machine
3) Virtual Machine (from .ova)
4) Custom Volume
Please enter the number of your choice: 2
Project to create the instance in [default=default]: default
Name of the new instance: mytest
Please provide the path to a disk, partition, or qcow2/raw/vmdk image file: disk.qcow2
Does the VM support UEFI booting? [default=yes]: yes
Does the VM support UEFI Secure Boot? [default=yes]: yes
Instance to be created:
Name: mytest
Project: default
Type: virtual-machine
Source: disk.qcow2
Source format: qcow2
Additional overrides can be applied at this stage:
1) Begin the migration with the above configuration
2) Override profile list
3) Set additional configuration options
4) Change instance storage pool or volume size
5) Change instance network
6) Add additional disk
7) Change additional disk storage pool
Please pick one of the options above [default=1]: 1
Converting image "disk.qcow2" to raw format before importing
Instance testtest successfully created
$
Here’s an example output. I used an empty directory and the tool managed to continue and generate the image. I do not know why it requires to supply an empty directory.
$ mkdir myrootfilesystem
$ sudo incus-migrate
The local Incus server is the target [default=yes]:
What would you like to create?
1) Container
2) Virtual Machine
3) Virtual Machine (from .ova)
4) Custom Volume
Please enter the number of your choice: 1
Project to create the instance in [default=default]:
Name of the new instance: mynewinstance
Please provide the path to a root filesystem: myrootfilesystem
Do you want to add additional filesystem mounts? [default=no]:
Instance to be created:
Name: mynewinstance
Project: default
Type: container
Source: myrootfilesystem
Additional overrides can be applied at this stage:
1) Begin the migration with the above configuration
2) Override profile list
3) Set additional configuration options
4) Change instance storage pool or volume size
5) Change instance network
6) Add additional disk
7) Change additional disk storage pool
Please pick one of the options above [default=1]: 1
Instance mynewinstance successfully created
$
Here’s the container.
$ incus list -c nsSt mynewinstance
+---------------+---------+-----------+-----------+
| NAME | STATE | SNAPSHOTS | TYPE |
+---------------+---------+-----------+-----------+
| mynewinstance | STOPPED | 0 | CONTAINER |
+---------------+---------+-----------+-----------+
$
[pgoetz@gecko ~]$ incus start rocky10 Error: Failed to run: /usr/bin/incusd forkstart rocky10 /var/lib/incus/containers /run/incus/rocky10/lxc.conf: exit status 1 (Failed getting os.UserHomeDir(): $HOME is not defined) Try incus info --show-log rocky10 for more info
More importantly, though, is that this is doesn’t create an container image from my qcow2 VM, unless this is something you execute after the container has been created, in which case how is this done?
Further, this appears to create a specific container instance rather than an image that can be launched. Although based on my use of LXD, it’s probably not terribly hard to create an image from a container instance.
You can’t use incus-migrate to convert a VM to a container, it supports either importing a local filesystem (typically another container or chroot) as a new container or importing an existing VM or VM template as a VM.
You can’t point it to a qcow2 or raw disk image and have it import that as a container.
Perplexity AI certainly hallucinated that response.
This begs the question then is there any way to do this? I have a customized copy of Rocky linux provided as a bootable ISO and what I really need is to convert this to an Incus container. Based on snooping around (and an unfortunate reliance on bad advice from an AI) I assumed it would be easier to convert a qcow2 or raw VM to an Incus container than trying to work with the ISO. Not sure if distrobuilder would help with this, but I can take a look at that next.
You can try to run incus-migrate from within the existing VM, then passing / as the path you want to import as a container. You may need to specify additional paths if the VM’s filesystem is partitioned. If it’s all in one partition, then / should work.
Be sure to stop as many services as you can before doing that though as transferring a running system with changing files can be a bit tricky.
The first thing I noticed is incus-migrate checks to see if incus is running. On the bare metal host:
[root@gecko ~]# incus-migrate The local Incus server is the target [default=yes]:
In the Rocky linux 10 VM (with no incus installation):
root@raccoon:~# /usr/local/bin/incus-migrate Please provide Incus server URL:
I’m including the next bit for informational purposes, as I don’t think this can work unless Incus is also running in the VM:
root@raccoon:~# /usr/local/bin/incus-migrate
Please provide Incus server URL: 192.168.1.7
Certificate fingerprint: b398fffa1840e28248b242a86eda930a32ca0c6fed7461a3781c516c1f352e32
ok (y/n)? y
1) Use a certificate token
2) Use an existing TLS authentication certificate
3) Generate a temporary TLS authentication certificate
Please pick an authentication mechanism above: 3
Your temporary certificate is:
-----BEGIN CERTIFICATE-----
MIIB1TCCAVqgAwIBAgIQfUFm56OEzrd3kcM0BLtnizAKBggqhkjOPQQDAzAyMRkw
FwYDVQQKExBMaW51eCBDb250YWluZXJzMRUwEwYDVQQDDAxyb290QHJhY2Nvb24w
HhcNMjUwOTMwMTY0MzEzWhcNMzUwOTI4MTY0MzEzWjAyMRkwFwYDVQQKExBMaW51
eCBDb250YWluZXJzMRUwEwYDVQQDDAxyb290QHJhY2Nvb24wdjAQBgcqhkjOPQIB
BgUrgQQAIgNiAATC4yXIKujan4b0I/t0UXgRzev6y7eR04S1pIyrP1PevBvr14l8
7pMmJb1FYmebIQf4WIzucMidYIzTKgRH8kqjIHHKGmL/dBaWnJu4K1Hw7LSgyKrU
gDE5r7k1q1B3t3qjNTAzMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF
BQcDAjAMBgNVHRMBAf8EAjAAMAoGCCqGSM49BAMDA2kAMGYCMQCwGF/OpDFezGOI
10g9+OwZCJu/nIngoCPM+9BOlZVMFBhJ75udsqm9qwugxNQ9z4gCMQDVmbIMFKgJ
S9w+/dNLHn+z2gtF685vY3tgFL3ilypUA1/LB8lMVqQCLH2382oDGVA=
-----END CERTIFICATE-----
A temporary client certificate was generated, use `incus config trust add` on the target server.
Press ENTER after the certificate was added to the remote server:
I’m not seeing any way to use incus config trust add to apply the temporary certificate to the bare metal Incus server. It looks like the temporary trust relationship needs to go the other way; i.e. originates on the server.
Option 1 worked flawlessly, and I didn’t need to install Incus in the VM! I thought it would create an image rather than a container instance, but it’s pretty easy to turn an instance into an image, so I’m calling this solved. Since the discussion was all over the map, I’m going to summarize the findings and mark this as solved.