---
title: Building Debian system images with vmdb2
author: Lars Wirzenius
date: work-in-progress
...

Introduction
=============================================================================

vmdb2 builds disk images with Debian installed. The images can be used
for virtual machines, or can be written to USB flash memory devices,
and hardware computers can be booted off them. It is a successor of
the vmdebootstrap program, written by the same author, to fix a number
of architectural problems with the old program. The new program is not
compatible with the old one; that would've required keeping the
problems, as well.

This manual is published as HTML at
<https://vmdb2-manual.liw.fi/> and as a PDF at
<https://vmdb2-manual.liw.fi/vmdb2.pdf>.

Why vmdb2 given vmdebootstrap already existed
-----------------------------------------------------------------------------

`vmdebootstrap` was the first attempt by Lars Wirzenius to write a
tool to build system images. It turned out to not be well designed.
Specifically, it was not easily extensible to be as flexible as a tool
of this sort should be.

Why vmdb2 given other tools already exist
-----------------------------------------------------------------------------

Lars likes to write tools for himself and had some free time. He
sometimes prefers to write his own tools rather than spend time and
energy evaluating and improving existing tools. He admits this is a
character flaw.

Also, he felt ashamed of how messy `vmdebootstrap` turned out to be.

If nobody else likes `vmdb2`, that just means Lars had some fun on his
own.


Installation
=============================================================================

You can get vmdb2 by getting the source code from git:

    git clone git://git.liw.fi/vmdb2

You can then run it from the source tree:

    sudo /path/to/vmdb2/vmdb2 ...

In Debian 10 ("buster") and its derivatives, you can also install the
vmdb2 package:

    apt install vmdb2

For any other systems, we have no instructions. If you figure it out,
please tell us how.


Getting started
=============================================================================

vmdb2 works by reading specification file with instructions for how an
image should be built, using YAML syntax, and following those
instructions. A minimal specification file example:

    steps:
      - mkimg: "{{ output }}"
        size: 4G

      - mklabel: gpt
        device: "{{ output }}"

      - mkpart: primary
        device: "{{ output }}"
        start: 0%
        end: 100%
        tag: root

      - kpartx: "{{ output }}"

      - mkfs: ext4
        partition: root

      - mount: root

      - debootstrap: stretch
        mirror: http://deb.debian.org/debian
        target: root

      - apt: install
        packages:
          - linux-image-amd64
        tag: root

      - grub: bios
        tag: root
        console: serial

The above creates a four gigabyte file, creates a GPT partition table,
a single partition, with an ext4 filesystem, and installs Debian release
stretch onto it. It also installs a kernel, and a boot loader.

To use this, save the specification into `test.vmdb`, and run the
following command:

    sudo vmdb2 test.vmdb --output test.img --verbose

This will take a long time, mostly at the `debootstrap` step.


Tags
-----------------------------------------------------------------------------

Instead of device filenames, vmdb2 steps refer to block devices inside
the image, and their mount points, by symbolic names called tags. Tags
are any names that the user likes, and vmdb2 does not assign meaning
to them. They're just strings.


Jinja2 expansion
-----------------------------------------------------------------------------

To refer to the filename specified with the `--output` or `--image`
command line options, you can use [Jinja2](http://jinja.pocoo.org/)
templating. The variables `output` and `image` can be used.

    - mkimg: "{{ output }}"

    - mklabel: "{{ image }}"

The difference is that `--output` creates a new file, or truncates an
existing file, whereas `--images` requires the file to already exist.
The former is better for image file, the latter for real block
devices.


Speed up image creation by caching the root filesystem
-----------------------------------------------------------------------------

Building an image can take several minutes, and that's with fast
access to a Debian mirror and an SSD. The slowest part is typically
running debootstrap, and that always results in the same output, for a
given Debian release. This means its easy to cache.

vmdb2 has the two actions `cache-roots` and `unpack-rootfs` and the
command line option `--rootfs-tarball` to allow user to cache. The
user uses the option to name a file. `cache-rootfs` takes the root
filesystem and stores it into the file as a compress tar archive
("tarball"). `unpack-rootfs` unpacks the tarball. This allows vmdb2 to
skip running debootstrap needlessly.

The specify which steps should be skipped, the `unless` field can be
used: `unpack-rootfs` sets the `rootfs_unpacked` flag if it actually
unpacks a tarball, and `unless` allows checking for that flag. If the
tarball doesn't exist, the flag is not set.

    - unpack-rootfs: root

    - debootstrap: stretch
      target: root
      unless: rootfs_unpacked

    - cache-rootfs: root
      unless: rootfs_unpacked

If the tarball exists, it is unpacked, and the `debootstrap` and
`cache-rootfs` steps are skipped.

It's possible to have any number of steps between the unpack and the
cache steps. However, note that if you change anything within those
steps, or time passes and you want to include the new packages that
have made it into Debian, you need to delete the tarball so it is run
again.

TODO: unless, caching, tags, jinja2

Step reference manual
=============================================================================

