Copying or moving Incus containers between hosts
Below, I will briefly explain how to transfer Incus containers between two Incus hosts that are not connected to a shared cluster. In my case, both hosts are equipped with ZFS-based container storage. See also: “Running Incus with ZFS in a VM and moving containers to a new storage pool”
Open API
If a container is to be moved between two hosts, a transfer path must first be created between the two Incus hosts. To do this, the API is made available on the network interface on the source host:
incus config set core.https_address [2001:db8::1]:8443
The IPv6 address in square brackets must, of course, be replaced with the IP address of your own interface. For an IPv4 address, the brackets are omitted.
Next, a trust token is generated on the source server:
incus config trust add sourcehost
The source server is added to the target server:
incus remote add sourcehost 2001:db8::1
The trust token previously issued by the source server must be entered at the end. As soon as
Client certificate now trusted by server: sourcehost
appears in the console, the first transfer of the container from the source server to the target server can take place.
Transferring data
The container’s root file system can be transferred in two ways:
- a) In one go, with downtime lasting as long as the data transfer. Recommended for small containers.
- b) In several steps via a second, incremental sync. With a few seconds to minutes of downtime. Recommended especially for larger containers with 100+ GB. Only works with file systems such as ZFS that support snapshots.
a) Simple transfer for smaller containers
# (on the source server)
incus stop mycontainer
# (on the target server)
incus copy sourcehost:mycontainer mycontainer --stateless
Or b): Incremental transfer
With incremental transfer, the current status of the container is first transferred in the background. The parts that were changed during the transfer (because the container was still in operation) are delivered in a second step. However, this second sync runs much faster because it only transfers a delta and not all data again.
Create snapshot on the source server:
incus snapshot create mycontainer
(The container remains in operation and is not stopped yet)
Start initial transfer to the target server:
incus copy sourcehost:mycontainer mycontainer --stateless
After the first transfer, the source container is terminated and a second, final sync is triggered:
# (on the source server)
incus stop mycontainer
incus snapshot create mycontainer
# (on the target server)
incus copy sourcehost:mycontainer mycontainer --refresh
Finally, the container is started on the target server:
incus config unset mycontainer volatile.apply_template
incus start mycontainer
Close API
Finally, the API on the source server can be closed again if it is not to be used for other purposes:
incus config unset core.https_address