Incus-migrate questions

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         
$

Hi -

I’m trying to create a container image, not a VM, so I used option 1. I already have a KVM VM.

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 |
+---------------+---------+-----------+-----------+
$

The documentation at How to import physical or virtual machines to Incus instances - Incus documentation does need some additions.

Hi Simos -

I tried almost exactly this. The container is created without error and shows up exactly like this:

[pgoetz@gecko ~]$ incus list
±-----------±--------±--------------------±-----±----------±----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
±-----------±--------±--------------------±-----±----------±----------+
| rocky10 | STOPPED | | | CONTAINER | 0 |
±-----------±--------±--------------------±-----±----------±----------+
| ubuntu2404 | RUNNING | 192.168.1.30 (eth0) | | CONTAINER | 0 |
±-----------±--------±--------------------±-----±----------±----------+

However if you try to start it, it blows up:

[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. :slightly_smiling_face:

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.

1 Like

Thank you. Will report findings back to this ticket.

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.

I wasn’t able to continue the experiment for now, as the instructions for installing Incus on Rocky linux provided here: How to install Incus - Incus documentation
seem to be incomplete. Rather than repeat something documented elsewhere, here is a link to the github problem report: Missing dependencies · Issue #3 · NeilHanlon/incus-rpm · GitHub

Option 1 is the easy one as it will just take a token you generate with incus config trust add on the target system.

Option 2 would require you writing that certificate into a file on the Incus system and then load it with incus config trust add-certificate

1 Like

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.

Converting any linux x86-64 VM into an Incus container instance:

  1. The VM needs to be running, and rsync must be installed.
  2. Make sure the following has been set on the Incus server:
    incus config set core.https_address :8443
  3. ssh into the VM and download incus-migrate
  4. Run incus-migrate as root:
    sudo ./bin.linux.incus-migrate.x86_64
  • Please provide Incus server URL: IP address or DNS server name of the Incus server

Check to make sure that the provided fingerprint matches that of the server you want to send the container image to

  • Select Option 1, Use a certificate token

On the Incus server, generate a certificate token:
incus config trust add certificate

Copy the resulting certificate token and paste into terminal on the VM in response to Please provide the certificate token:

  • What would you like to create? Select 1 for container
  • Name of the new instance: Can be any valid container name
  • Please provide the path to a root filesystem: /
  • Do you want to add additional filesystem mounts? Typically, no. You don’t want the EFI partition, for example.
  • Select 1) Begin the migration with the above configuration

That’s it. When completed, a new container instance with the name you gave it will appear on the Incus server.