Import other Linux distributions and create containers from them.
By default, sdme new creates an overlayfs clone of your host root filesystem. You can also import and use other distributions.
For example, to import Ubuntu:
sudo sdme fs import docker.io/ubuntu
sdme infers ubuntu from the final repository component, ignoring an OCI tag such as :latest. For files, directories, and URLs it uses the final path component and removes recognized archive or image suffixes. Use --name NAME when you want an alias or the inferred value is not a valid lowercase sdme name.
sdme pulls the OCI image, extracts it, and installs the minimum packages needed for systemd-nspawn to boot it (systemd, dbus, etc). See import prehooks below for details on how this works.
sudo sdme new -r ubuntu
Or give it a name:
sudo sdme new --name mybox -r ubuntu
This creates a container using the imported Ubuntu rootfs instead of cloning the host. The imported rootfs is reusable: you can create multiple containers from the same base.
Containers created from an imported rootfs use an overlayfs upper layer by default. On a host with btrfs available, you can back a container with a copy-on-write btrfs subvolume instead:
sudo sdme new --name mybox -r ubuntu --storage btrfs
The btrfs backend gives the container a real filesystem rather than an overlay mount. That lets you run nested containers inside it (Docker, podman, or another sdme), preserves setuid bits and file capabilities under --userns, and enables a per-container disk cap. Host clones (sdme new with no -r) always use overlay; only imported rootfs can use btrfs.
Cap a btrfs container's disk usage with --disk:
sudo sdme new --name build -r ubuntu --storage btrfs --disk 4G
sdme ps then shows a DISK column with used and limit for capped containers, and a write past the cap fails with "No space left on device". You can change the cap later with sudo sdme set build --disk 8G.
The btrfs backend needs btrfs-progs installed, and --disk additionally needs btrfs simple quotas (btrfs-progs and a kernel from the 6.7 series or newer). See the architecture guide for the storage model and its trade-offs.
sudo sdme fs ls
sudo sdme fs rm ubuntu
You cannot remove a rootfs while containers using it still exist. The rootfs is the overlayfs lower layer for those containers, so remove the containers first with sdme rm, then the rootfs.
Any OCI image with a systemd-based distro can be imported. Here are the officially tested ones:
sudo sdme fs import docker.io/debian:stable
sudo sdme fs import docker.io/ubuntu
sudo sdme fs import quay.io/fedora/fedora
sudo sdme fs import quay.io/centos/centos:stream10
sudo sdme fs import quay.io/almalinuxorg/almalinux:9
sudo sdme fs import docker.io/lopsided/archlinux
CachyOS is Arch-based and uses the same base image. If you're running CachyOS as your host, cloning with sudo sdme new (no -r) gives you a CachyOS container directly.
sudo sdme fs import registry.opensuse.org/opensuse/tumbleweed --name opensuse
NixOS requires a separate build process. See the build script and nix expression in the repository for an example.
sdme fs import also supports tarballs, directories, and QCOW2 disk images. Cloud images from Ubuntu, Fedora, and others can be imported directly from a URL. On x86_64:
sudo sdme fs import https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64-root.tar.xz --name ubuntu-cloud
On aarch64:
sudo sdme fs import https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-arm64-root.tar.xz --name ubuntu-cloud
Cloud images typically ship with their own SSH server, may expect cloud-init for initial configuration, and often have a default or locked root password. They are well suited to run with --private-network so their services don't conflict with the host:
sudo sdme new --name mycloud -r ubuntu-cloud --private-network
You can also build a rootfs with debootstrap and import the resulting directory. On x86_64:
sudo debootstrap --include=systemd,dbus,systemd-resolved,login noble /tmp/noble http://archive.ubuntu.com/ubuntu
On aarch64 (including Apple Silicon via lima-vm):
sudo debootstrap --include=systemd,dbus,systemd-resolved,login noble /tmp/noble http://ports.ubuntu.com/ubuntu-ports
Then import it:
sudo sdme fs import /tmp/noble --name ubuntu-debootstrap
See sdme fs import --help for the full list of supported sources.
When sdme imports a base OS image, it detects the distribution family and runs a set of commands inside the rootfs (via chroot) to install the packages needed for systemd-nspawn to boot it: systemd, dbus, login utilities, etc.
To see the current prehook commands for all distro families:
sudo sdme config get
This shows the full configuration, including the built-in defaults for each distro family (debian, fedora, arch, suse).
You can override the import prehook for any distro family. The value is a JSON array of commands:
sudo sdme config set distros.debian.import_prehook '["apt-get update","apt-get install -y systemd dbus"]'
To restore the built-in default, clear the override:
sudo sdme config set distros.debian.import_prehook ''
The --install-packages flag on sdme fs import controls whether prehooks run at all. By default sdme runs them only when it detects that systemd is missing from the rootfs.