sdme 0.4.2

Booted systemd-nspawn containers with OCI and Kubernetes support
Documentation
# sdme

The systemd machine editor: a single static binary that creates and manages
Linux containers using systemd-nspawn with overlayfs. No daemon, no runtime
dependency beyond systemd. Written in Rust.

sdme is primarily a **development tool**. It makes systemd-nspawn containers
first-class citizens on any Linux machine, letting you spin up almost any
distro that can boot with systemd.

## Containers from your host filesystem

The simplest way to start is to clone your running system. This creates an
overlayfs snapshot of your host, boots systemd inside it, and drops you into
your own shell with your $HOME and configs intact. Install packages, change
configs, break things; the host is untouched.

```
sudo sdme new
```

Manage containers with:

```
sudo sdme ps              # list containers and their status
sudo sdme join <name>     # re-enter a running container
sudo sdme stop <name>     # stop a container
sudo sdme rm <name>       # remove a container
```

## Importing any root filesystem

Beyond cloning your host, sdme can import a root filesystem from virtually any
source: OCI registries, local directories, tarballs, URLs, or QCOW2 cloud
images. Each imported rootfs becomes a reusable template. Spin up as many
containers as you want from it.

```
sudo sdme fs import ubuntu docker.io/ubuntu:24.04
sudo sdme fs import fedora quay.io/fedora/fedora
sudo sdme fs import archlinux docker.io/archlinux

sudo sdme new -r ubuntu
sudo sdme new -r fedora
sudo sdme new -r archlinux
```

sdme has specific distribution support for Debian, Ubuntu, Fedora, CentOS,
AlmaLinux, openSUSE, Arch Linux, CachyOS, and NixOS. This ensures that the
right packages are present in what we consider a base filesystem for spinning
up a working container.

See [docs/usage.md](docs/usage.md) for the full list of import sources.

## Fully featured containers

These containers are fully featured. They support all the expected
systemd-nspawn capabilities: port binding, private networking, bind mounts,
and complex security configurations. They are useful when you want to install
and run services from the regular distribution repositories or your own
packages, anything you would normally do on a real machine.

The result is that you can run pretty much any systemd-capable distro as a
container on any Linux machine.

See [security, networking, and resource limits](docs/usage.md#8-security-networking-and-resource-limits)
and the [security architecture](docs/architecture.md#14-security) for details.

---

## Experimental features

Everything below this line is experimental. These features work and are
actively developed, but their interfaces may change.

### OCI application support

sdme can query OCI container registries, flatten the root filesystem of any
image, and make it a usable base filesystem.

Because we now support importing from OCI, it is natural to differentiate
between **base filesystem images** like Debian and Fedora, and **application
images** like nginx and MySQL, images that normally bind on ports and share
volumes.

The way this works is by placing the entire OCI application (e.g. the nginx
container) as a chroot inside the systemd container and wiring it all up so
that it looks like a Docker or Podman environment. The application runs as a
systemd service inside a booted container.

```
sudo sdme fs import redis docker.io/redis --base-fs=ubuntu
sudo sdme new -r redis
```

Port bindings and volume bindings are wired to the systemd container itself:

```
sudo sdme logs --oci <name>
sudo sdme exec --oci <name> redis-cli ping
```

See [OCI integration](docs/architecture.md#16-oci-integration) for the full
story.

### Dual security model and pods

Because the systemd container is running the OCI application as a service, you
get two independent layers of configuration.

The OCI application has a security model resembling Docker and Podman, while
the systemd container can have different configurations and security
permissions. This separation gives you fine-grained control over what each
layer can do.

Containers can be placed in a **pod**, a shared network namespace. Pods can
be shared across systemd containers, but the OCI applications themselves can
also be placed in the same or a different pod. This lets you compose a
**control plane** and an **application plane** separately, from both the
network and isolation perspective.

### Kubernetes pod support

The next natural evolution is Kubernetes pod support. sdme can consume Kube Pod
YAML and set up the pod on a systemd container.

Volumes and port bindings are wired through, multiple OCI applications can be
placed in the same systemd container, and the common Kubernetes features are
supported: config maps, secrets, and probes.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: nginx
    image: docker.io/nginx:latest
    ports:
    - containerPort: 80
  - name: redis
    image: docker.io/redis:latest
  - name: mysql
    image: docker.io/mysql:latest
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: secret
```

```
sudo sdme kube apply -f pod.yaml --base-fs ubuntu
```

See [Kubernetes pod support](docs/architecture.md#17-kubernetes-pod-support)
for the full spec.

### Exporting rootfs and containers

Export any imported rootfs or container filesystem as a directory, tarball, or
raw disk image. Copy containers to other machines, share rootfs templates, or
produce bootable VM images for hypervisors like Cloud Hypervisor and QEMU.

```
sudo sdme fs export ubuntu ubuntu.tar.zst
sudo sdme fs export --container <name> container.tar.gz
sudo sdme fs export ubuntu ubuntu.raw --fmt raw
```

## Further reading

- [docs/usage.md](docs/usage.md): install, lifecycle, rootfs management,
  networking, OCI, pods, security, builds
- [docs/architecture.md](docs/architecture.md): internals, design, OCI
  bridging, Kubernetes mapping