I’m doing a (custom) Debian installer (just a hobby, won’t be useful and reliable like the official one) for my Thinkpad X220 laptop. This has been brewing since August 2018, and is starting to get ready. I’d like no feedback on things people like/dislike in the official installer, as my installer resembles it not at all.

I’ve currently installed Debian on my X220, with full disk encryption, and it seems to boot and allow me to log in via SSH. This implies that I’ll get something else to be stubborn about within a few months, and I’d like to let someone else make it work other people’s computers. Any volunteers are welcome, but I won’t promise I’ll have much energy to help.

To be clear, my installer only works on my X220. Not your X220, and not on any other computer. But it’d probably be feasible to make it work on other PCs.

It’s called v-i, short for “vmdb2 installer”, not to be confused with d-i, the official Debian installer. vmdb2 is my program for creating Debian based virtual machine images. It is also used to create images for Raspberry Pis.

Why write my own installer? I’m going to plead temporary stubbornness. I thought that this shouldn’t be hard, given I already had vmdb2. That was in August 2018.

More seriously, the official Debian installer is great in many ways, but I think it’d be possible to improve on it. For one thing, d-i is based on a separate packaging format (udeb) for any software that’s part of the installer. For another thing, automating installs with d-i requires writing “pre-seed files” that answer questions that Debian packages ask, but it’s limited to answering existing questions. I need to install Debian on bare metal hardware often enough that I’d like a bit more and easier automation.

v-i uses standard Debian packages, and allows using Ansible for configuring the system being installed. For my X220 with 16 gigabytes of RAM and 200 gigabytes of disk, the constraints for which d-i was developed aren’t relevant. Obviously, that doesn’t apply to all computers, but it applies to all the ones I have or am likely to get.

With fewer constraints, the limitations of d-i, and its fundamental interactive nature, have become a little annoying to me, when I need to use it often. I’d like something more flexible that I can automate easily. I think I will have that in v-i, if I can find the time and energy to polish it a bit. I’d like to be able to install every PC I have with it, at least. I’ve done the first successful install today, with Debian bullseye and LUKS disk encryption.

It’d be nice if it worked for others as well, but I’m not sure I won’t have the time and energy to do that. It took me over two years to get v-i working on a well-supported target, and adding support for more hardware doesn’t sound like the kind of thing I’d enjoy. Maybe someone wants to help? I will at least write some docs to make it plausible for someone else to do that work.

To use v-i, you write the v-i image on a USB drive, and boot off that. This gives you a live Debian system, and you run vmdb2 to install Debian onto the hard drive of the system you booted. To do that, you need to write a YAML file that describes to vmdb2 what the installed system should look like: what partitions and file systems there should be, what software installed, etc.

Here’s an example, the YAML file for my X220.

steps:
  - mklabel: gpt
    device: "{{ image }}"

  # EFI partition. This MUST be vfat and cleartext so that UEFI BIOS
  # can handle it.
  - mkpart: primary
    device: "{{ image }}"
    start: 0%
    end: 500M
    tag: efi

  - mkfs: vfat
    partition: efi

  # /boot partition. This will be cleartext, because GRUB doesn't seem
  # to support LUKS2 yet.
  - mkpart: primary
    device: "{{ image }}"
    start: 500M
    end: 1G
    tag: boot

  - mkfs: ext2
    partition: boot

  # The physical volume for LVM. This will be encrypted and the
  # unlocked, opened variant will be used as the physical volume for
  # LVM2.
  - mkpart: primary
    device: "{{ image }}"
    start: 1G
    end: 100%
    tag: cleartext_pv0

  - cryptsetup: cleartext_pv0
    password: asdf
    name: pv0

  - vgcreate: vg0
    physical:
      - pv0

  - lvcreate: vg0
    name: root
    size: 10G

  - mkfs: ext4
    partition: root

  # Mount the file systems on top of each other.
  - mount: root

  - mount: boot
    dirname: /boot
    mount-on: root

  - mount: efi
    dirname: /boot/efi
    mount-on: boot

  - virtual-filesystems: root

  # Install Debian.

  - unpack-rootfs: root

  - debootstrap: bullseye
    mirror: http://deb.debian.org/debian
    target: root
    unless: rootfs_unpacked

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

  - cache-rootfs: root
    unless: rootfs_unpacked

  # Create fstab and crypttab
  - fstab: root

  # Install additional packages. These are not in the rootfs tarball,
  # while I keep changing this list: it's easier and faster to iterate
  # if the rootfs tarball doesn't need to be re-generated from
  # scratch.
  - apt: install
    packages:
      - console-setup
      - cryptsetup
      - cryptsetup-initramfs
      - dosfstools
      - ifupdown
      - locales-all
      - lvm2
      - python3
      - ssh
    tag: root

  # Configure the system with Ansible.
  - ansible: root
    playbook: x220.yml

  # Install GRUB as the bootloader.
  - grub: uefi
    tag: root
    efi: efi
    quiet: true
    image-dev: "{{ image }}"

The code is in git at https://gitlab.com/larswirzenius/v-i, if you’re curious.