A storage pool in Incus is a driver and a source. There are several drivers: zfs, btrfs, lvm, ceph, dir. dir is the most boring one, a directory. And a directory is allowed to be a tmpfs mount.

mount -t tmpfs -o size=32g none /mnt/tmpfs
incus storage create tmpfs dir source=/mnt/tmpfs

From here on, every instance that starts on this pool lands in memory.

Create

incus launch images:debian/trixie runner --storage tmpfs

Back up

incus publish turns the instance into an image. If it’s still running, Incus demands --force — it gets stopped briefly and restarted automatically afterward. The aliases rotate the generations:

incus publish runner --alias runner-current --compression none --reuse --force
incus image delete runner-old || true
incus image alias rename runner runner-old || true
incus image alias rename runner-current runner

runner is now the last clean state, runner-old the one before.

dir has no real snapshots — publish copies the rootfs via rsync before it becomes an image. On tmpfs that means: for the duration of the publish, the container needs roughly double its size in RAM.

Restore

Instance gone, image still there — one command:

incus launch runner runner --storage tmpfs

Back to the state before that:

incus launch runner-old runner --storage tmpfs

Delete

incus delete --force runner

All at Once

❯ incus launch docker.io:library/alpine:edge runner -s tmpfs
Launching runner

~
❯ incus publish runner --alias runner
Error: The instance is currently running. Use --force to have it stopped and restarted

~
❯ incus publish runner --alias runner --force
Instance published with fingerprint: e5337dc9f3751419f4720f64397e528801d53e57cb0ab5fd5769f84d6c8a6183

~
❯ incus rm -f runner

~
❯ incus launch runner runner
Launching runner

~
❯ incus console --show-log runner
/ #

Just the Database, If You Want

You don’t have to put the whole instance on tmpfs. A volume on the pool can be attached to a single instance as a device:

incus storage volume create tmpfs runner-db
incus config device add runner incusdb disk \
    pool=tmpfs source=runner-db path=/var/lib/incus/database

The rootfs stays where it was, only dqlite lands in RAM — probably the actual bottleneck of an Incus daemon.

In Practice

This is how I back up the runner for incus-compose’s CI. 23 minutes of CI became 8.


By René Jochum - LLM Assistet. License: CC-BY-4.0.