systemd-importd is the background service behind every machinectl import, export and download of a container or VM image. You will finish with a safe workflow for inspecting image storage and moving images in and out of it without guessing at what changed. The examples match systemd 255.4-1ubuntu8.17 installed on Ubuntu here.
Allow about 20 minutes for a read-only check, or longer for an actual image transfer. You need a shell, the systemd package and an image source you trust. Importing, downloading, exporting and removing images changes system state and normally needs elevated privileges. This guide does not start, stop or remove a machine.
Check the version and the command path first. These are ordinary, read-only commands:
$ machinectl --version
systemd 255 (255.4-1ubuntu8.17)
$ command -v machinectl
/usr/bin/machinectl
$ command -v systemd-importd || true
$ ls -l /usr/lib/systemd/systemd-importd
-rwxr-xr-x 1 root root ... /usr/lib/systemd/systemd-importd
The daemon is the service implementation, not the command you actually type. machinectl asks systemd's D-Bus service to perform the transfer, so do not try to invoke /usr/lib/systemd/systemd-importd directly as a replacement for it.
Checkpoint: Confirm the operations available on this host:
$ machinectl --help | sed -n '/Image Transfer Commands:/,/Options:/p'
Image Transfer Commands:
pull-tar URL [NAME] Download a TAR container image
pull-raw URL [NAME] Download a RAW container or VM image
import-tar FILE [NAME] Import a local TAR container image
import-raw FILE [NAME] Import a local RAW container or VM image
import-fs DIRECTORY [NAME] Import a local directory container image
export-tar NAME [FILE] Export a TAR container image locally
export-raw NAME [FILE] Export a RAW container or VM image locally
List images before choosing a destination name. This normally does not need sudo:
$ machinectl --no-pager list-images
MACHINE CLASS SERVICE OS VERSION ADDRESSES
...
The exact columns and rows depend on the host. An empty table means no image is currently visible to machinectl, not proof that an import failed. Check transfers separately:
$ machinectl --no-pager list-transfers
IDX TYPE SOURCE DESTINATION PROGRESS
... ... ... ... ...
No rows is normal when nothing is downloading or importing. If a transfer is active, record its index before considering cancellation, because cancellation itself changes state:
$ sudo machinectl cancel-transfer TRANSFER_ID
Replace TRANSFER_ID with an identifier from the list, not the image name. If you cancel a transfer, rerun list-transfers and keep the partial result out of service until you have checked what it left behind.
Image names live below /var/lib/machines. Choose a short, unique name such as test-debian, and check the destination before importing:
$ IMAGE_NAME=test-debian
$ machinectl image-status "$IMAGE_NAME"
Failed to query image: No such file or directory
That missing-image error is useful here: it shows the name is not already in use. If you see image properties instead, stop and choose another name or deliberately plan a replacement.
For a local archive, inspect it without extracting it:
$ tar -tf /path/to/container.tar | sed -n '1,20p'
$ test -r /path/to/container.tar && echo 'archive is readable'
archive is readable
An archive that opens cleanly is not the same as an archive worth trusting. Confirm its provenance, expected operating system and intended architecture. For a remote URL, use a trusted HTTPS source and follow that publisher's checksum or signature instructions. The import service can verify some downloads when the relevant machinectl verification options and signed metadata are available, but a transfer completing is not a security review.
Warning: This writes an image into /var/lib/machines. Check the name and archive first, and keep the original archive until the result has been inspected.
Import a TAR container image with root privileges:
$ sudo machinectl import-tar /path/to/container.tar "$IMAGE_NAME"
Enqueued transfer job for container image.
The wording can vary by systemd version, so verify the result rather than trusting the message:
$ machinectl --no-pager image-status "$IMAGE_NAME"
NAME TYPE RO USAGE CREATED MODIFIED PATH
test-debian dir no ... ... ... /var/lib/machines/test-debian
A TAR import is stored as a directory tree or Btrfs subvolume under the chosen name. The service may start on demand, so an inactive result from systemctl is-active systemd-importd while no transfer is running is not by itself an error.
Recovery: If the imported image is wrong, do not overwrite it by guessing at a force option. Preserve any needed logs or data first, then remove the named image only after checking the target:
$ machinectl image-status "$IMAGE_NAME"
$ sudo machinectl remove "$IMAGE_NAME"
$ machinectl image-status "$IMAGE_NAME"
Failed to query image: No such file or directory
remove is destructive. Treat the second command as a deliberate deletion, not routine cleanup.
If you already have a prepared root directory, import-fs imports it as a container image. This also changes /var/lib/machines, so use a disposable directory and a distinct name:
$ sudo machinectl import-fs /path/to/prepared-root test-directory
$ machinectl --no-pager image-status test-directory
The source directory is not a generic installer: it must already contain a usable container filesystem, and importing it does not prove the container will boot. Check its files and metadata before attempting to run it. To undo this test, verify the exact name and use sudo machinectl remove test-directory.
Exporting reads an image and writes a new archive. Use a new destination so shell redirection or an existing path cannot destroy a useful backup:
$ OUTPUT=/tmp/test-debian.tar.new
$ sudo machinectl export-tar "$IMAGE_NAME" "$OUTPUT"
$ test -s "$OUTPUT" && tar -tf "$OUTPUT" | sed -n '1,10p'
$ mv -- "$OUTPUT" /path/to/backup/test-debian.tar
The final mv is only safe once the temporary file is non-empty and its contents look right. If the export fails, remove the incomplete file in /tmp and the original backup stays untouched. Use export-raw with a destination ending in .raw when you need a raw VM or container image rather than a TAR archive.
pull-tar and pull-raw download directly through the same service. A download is both network activity and a write into local image storage:
$ sudo machinectl pull-tar https://example.invalid/trusted-image.tar test-remote
$ machinectl --no-pager list-transfers
$ machinectl --no-pager image-status test-remote
That URL is a placeholder and is not expected to work. Replace it only with a source you have independently verified, and never paste an untrusted URL into a privileged command. Use the command's supported verification settings where the source publishes matching signatures or checksums, and watch the transfer list until it disappears before treating the image as ready.
machinectl versions.machinectl client.image-status.