Migrating containers from legacy LXC 1.x to current LXD 3.x

I am running a legacy LXC version 1.0.7 host with a dozen containers.

My current project requires to transfer these containers to a new host running LXD 3.

Since LXD 2, transferring of containers in between hosts is super easy, and I have done it several times. But I do not know how to package the LXC 1.x containers in a way that makes them accessible for LXD 3. There seems to be no export type of command available, and the container structure looks versy different in the file system.

Any advice would be much appreciated!

If that’s an option, you could update the source to LXC 2.0 or 3.0, then use lxc-to-lxd to import the containers.

Though I suspect in this case, a manual approach may be simpler.

What you’d do for that is create very small new containers on LXD, possibly using a small image like Alpine, then with the container running (set it privileged with security.privileged=true), rsync the content of your old container over the new one, then reboot it and make sure everything works.

So that’s effectively rsync of the container’s rootfs and then tweaking any configuration that needs tweaking, just make sure your destination container is privileged if your source one was (pretty likely), you can always try making the container unprivileged afterwards, but you don’t want to mix and match during transfer.

Thank you Stéphane!
Unfortunately I cannot update the host system that hosts the LXC 1.0.7 containers.
Instead I rsynced the content of /var/lib/lxc to a separate directory on my LXC 3 host. Then I have tried to convert them using sudo lxc-to-lxd --lxcpath /lxc-migration/lxc --dry-run --debug <container>. I was able to comment out stuff from the configuration that are not required anymore. But the converter doesn’t recognize overlayfs.

Couldn't find the container rootfs 'overlayfs:/...'

All my containers are using overlayfs, and I have the data for all containers. They are all overlaid over a base ubuntu trusty container. I already tried to change the absolute paths in lxc.rootfs to point to the paths where all container data has been moved to, but lxc-to-lxd doesn’t seem to work when overlayfs is present at all.

Is there a way to “flatten” a chain over overlayfs?

I had same issue I created same os version lxd and moved rootfs with cp - rvp. After this lxc publish container and you are done. lxc start and it works as long as network is configured correctly

I have found a way to make a flattened rootfs for each of my overlayfs-based containers. Basically, manually mount them with overlayfs and then set the rootfs parameter in the LXC container config to that rootfs-mounted directory.

But, I am having trouble still to import the LXC containers into LXD: I am using LXD on ZFS.

the lxc-to-lxd converter apparently doesn’t support ZFS, the output looks like this:

console output
LXD container config:
 "architecture": "x86_64",
 "config": {
  "security.privileged": "true"
 "devices": {
  "convert_net0": {
   "hwaddr": "00:16:3e:4e:62:db",
   "nictype": "bridged",
   "parent": "lxcbr0",
   "type": "nic"
  "eth0": {
   "type": "none"
 "name": "ubuntu_trusty_amd64",
 "profiles": [
 "source": {
  "type": "none"
Creating the container
Copying container rootfs
Traceback (most recent call last):
  File "/usr/bin/lxc-to-lxd", line 621, in <module>
    container_name, args)
  File "/usr/bin/lxc-to-lxd", line 556, in convert_container
FileNotFoundError: [Errno 2] No such file or directory: '/var/lib/lxd/containers/ubuntu_trusty_amd64/rootfs'

I was wondering if @stgraber’s approach—just copying the rootfs into a dummy container—would work on ZFS, too?

i think the @stgraber approach works too i do it in different manner like

cd in the rootfs you want to import

then tar zcf rootfs.tar.gz *

after you have to write the metadata.yaml

vim metadata.yaml and add:

architecture: “x86_64”
creation_date: 1582129602 # <-- Put your current, to get current date in Unix time, use date +%s command
architecture: “x86_64”
description: “Devuan Beowulf webproxy (20200220)”
os: “devuan”
release: “beowulf”

after make a tar

tar zcf metadata.tar.gz metadata.yaml

and then

lxc image import metadata.tar.gz rootfs.tar.gz --alias thenameyoulike

i do pratically the same with debootstrap to create already configured images.

to me works anyway check the permissions around some can be different

Same problem here, migration from lxc to lxd on 2 differents servers.

@alv solution work with small container but with bigger one I don’t have enough space on my root partition, not enough for import image (my storage is on a big zfs pool but probably not the image space…)

So I tried @stgraber solution, rune a small priviledged alpine container, rsync my rootfs and restart but container don’t start anymore :

    lxc info --show-log suivi
Name: suivi
Location: none
Remote: unix://
Architecture: x86_64
Created: 2021/01/16 13:35 UTC
Status: Stopped
Type: container
Profiles: lanprofile


lxc suivi 20210116191346.439 WARN     cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory "/sys/fs/cgroup/cpuset//lxc.monitor.suivi"
lxc suivi 20210116191346.443 WARN     cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory "/sys/fs/cgroup/cpuset//lxc.payload.suivi"
lxc suivi 20210116191346.506 ERROR    utils - utils.c:lxc_can_use_pidfd:1846 - Kernel does not support pidfds
lxc suivi 20210116191346.534 ERROR    dir - storage/dir.c:dir_mount:152 - No such file or directory - Failed to mount "/var/snap/lxd/common/lxd/containers/suivi/rootfs" on "/var/snap/lxd/common/lxc/"
lxc suivi 20210116191346.534 ERROR    conf - conf.c:lxc_mount_rootfs:1258 - Failed to mount rootfs "/var/snap/lxd/common/lxd/containers/suivi/rootfs" onto "/var/snap/lxd/common/lxc/" with options "(null)"
lxc suivi 20210116191346.534 ERROR    conf - conf.c:lxc_setup_rootfs_prepare_root:3141 - Failed to setup rootfs for
lxc suivi 20210116191346.534 ERROR    conf - conf.c:lxc_setup:3277 - Failed to setup rootfs
lxc suivi 20210116191346.534 ERROR    start - start.c:do_start:1218 - Failed to setup container "suivi"
lxc suivi 20210116191346.537 ERROR    sync - sync.c:__sync_wait:36 - An error occurred in another process (expected sequence number 5)
lxc suivi 20210116191346.543 WARN     network - network.c:lxc_delete_network_priv:3185 - Failed to rename interface with index 0 from "eth0" to its initial name "mac2072cfd6"
lxc suivi 20210116191346.543 ERROR    lxccontainer - lxccontainer.c:wait_on_daemonized_start:860 - Received container state "ABORTING" instead of "RUNNING"
lxc suivi 20210116191346.545 ERROR    start - start.c:__lxc_start:1999 - Failed to spawn container "suivi"
lxc suivi 20210116191346.545 WARN     start - start.c:lxc_abort:1018 - No such process - Failed to send SIGKILL to 11171
lxc 20210116191346.694 WARN     commands - commands.c:lxc_cmd_rsp_recv:126 - Connection reset by peer - Failed to receive response for command "get_state"

Any suggestion ?

Oups, found my answer here [Solved] LXD 3.21, container refuses to start

Sorry for the noise