geoffwilliams@home:~$

Debian 12 bootable USB

Let’s make a Debian 12 bootable USB. The idea is too boot from the USB and have it fully wipe the disk and bring up a blank server on the network. We would then be able to apply our Standard Operating Environment (SOE) to the new server to fully prepare it for workloads.

The official instructions from Debian are here, at time of writing the procedure is:

  1. Prepare USB stick
  2. Loopback mount installer ISO
  3. Copy to USB
  4. Copy preseed.cfg and related files to USB
  5. Boot the USB

These are my notes from creating a Debian 12 server USB installer with the goal to wipe the entire system and partition with LVM.

Overall straight-forward process with the exception of setting up preseed.cfg which is somewhat voodoo like.

Step 1: Download latest Debian ISO image

  • Debian netinst is perfect for minimal servers. I used debian-12.8.0-amd64-netinst.iso

Step 2: Find a USB stick and label it

  • 32GB+ USB 3 sticks can be got very cheap these days and are perfect (we only need less then 1 GB). Basically anything you can find around the house should work but faster USB versions would let you prepare and boot the OS a bit quicker
  • Label the stick somehow. You don’t want to accidentally boot it and destroy your system

Step 3: Prepare USB stick

Step 4: Copy preseed.cfg and any other needed files to USB stick

eg:

cp preseed.cfg /mnt/data/preseed.cfg

Step 5: Boot the USB

  • You know the drill ;-)

Preparing preseed.cfg

The most difficult part of the whole process is preparing preseed.cfg. There is no complete reference doc for this file covering all options because its up to individual packages to define how they can be configured during installation.

There’s a few points to bear in mind when writing preseed.cfg

  • You can extract the preseed.cfg answers from a Debian system that was interactively installed
  • Boot your USB stick/equivalent files in VirtualBox - much faster then burning a bunch of USB sticks
  • The partitioning setup is particularly difficult
  • Don’t expect to get it right first time
  • Do the absolute minimum required in preseed.cfg. Aim is to produce a minimal system with just enough access to boot and setup SSH. Rest of configuration should be done over SSH with ansible or Puppet
  • EUFI and BIOS installs are different

Conclusion

If you have a more than a handful of physical machines that need to be configured identically, its worth spending some time to get automated USB installs working. It’s really satisfying to watch the USB nuke the system and fully setup Debian. After applying an SOE you have a usable system and can then apply other automations to do things like install Kubernetes or other server software.

While these notes are targeted at servers, there’s no reason why they couldn’t be adapted for workstations. It’s the perfect way to prepare a fleet of laptops, for example.

Example preseed.cfg

# from https://github.com/chef/bento/blob/main/packer_templates/http/debian/preseed.cfg

#_preseed_V1
# Automatic installation
d-i auto-install/enable boolean true

d-i netcfg/choose_interface select auto
d-i netcfg/link_wait_timeout string 120
d-i netcfg/dhcp_timeout string 120
d-i netcfg/dhcpv6_timeout string 120

# Preseeding only locale sets language, country and locale.
d-i debian-installer/language string en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US.UTF-8

d-i console-setup/ask_detect boolean false
d-i debconf/frontend select noninteractive

# Keyboard selection.
d-i keyboard-configuration/xkb-keymap select us
d-i keymap select us

choose-mirror-bin mirror/http/proxy string
d-i apt-setup/use_mirror boolean true
d-i base-installer/kernel/override-image string linux-server

### Clock and time zone setup
d-i clock-setup/utc boolean true
d-i clock-setup/utc-auto boolean true
d-i time/zone string UTC




### Mirror settings
# If you select ftp, the mirror/country string does not need to be set.
d-i mirror/country string manual
d-i mirror/http/directory string /debian/
d-i mirror/http/hostname string httpredir.debian.org
d-i mirror/http/proxy string



# partman
# =======
# from https://serverfault.com/questions/1077958/preseeding-debian-11-fully-unattended-get-rid-of-questions


# This makes partman automatically partition without confirmation.
# Use LVM for partitioning
d-i partman-basicfilesystems/no_swap boolean false
d-i partman-auto/method string lvm

# And the same goes for the confirmation to write the lvm partitions.
d-i     partman-lvm/confirm boolean true

# Really, please don't prompt me!
d-i     partman-lvm/confirm_nooverwrite boolean true


d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-auto-lvm/guided_size string max
d-i partman-auto-lvm/new_vg_name string debian
d-i partman/early_command string \
        debconf-set partman-auto/disk "$(list-devices disk | head -n1)" ; \
        debconf-set grub-installer/bootdev "$(list-devices disk | head -n1)"
d-i partman-auto/choose_recipe select gpt-efi-boot-lvm
d-i partman-auto/expert_recipe string \
        gpt-efi-boot-lvm :: \
              512 512 512 fat32 \
                      $primary{ } \
                      method{ efi } \
                      format{ } \
                      mountpoint{ /boot/efi } \
              . \
              1024 1024 1024 ext4 \
                      $primary{ } \
                      $bootable{ } \
                      method{ format } \
                      format{ } \
                      use_filesystem{ } \
                      filesystem{ ext4 } \
                      mountpoint{ /boot } \
              . \
              100 1000 -1 lvm \
                      $defaultignore{ } \
                      $primary{ } \
                      method{ lvm } \
                      vg_name{ debian } \
              . \
              1024 3072 -1 ext4 \
                      $lvmok{} \
                      lv_name{ root } \
                      in_vg{ debian } \
                      method{ format } \
                      format{ } \
                      use_filesystem{ } \
                      filesystem{ ext4 } \
                      mountpoint{ / } \
              .

d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

# Force UEFI booting ('BIOS compatibility' will be lost). Default: false.
d-i partman-efi/non_efi_system boolean false
d-i partman-partitioning/choose_label select gpt
d-i partman-partitioning/default_label string gpt


### Account setup
d-i passwd/root-login boolean false
d-i passwd/user-fullname string geoff
d-i passwd/user-uid string 1000
d-i passwd/user-password password password
d-i passwd/user-password-again password password
d-i passwd/username string geoff

# The installer will warn about weak passwords. If you are sure you know
# what you're doing and want to override it, uncomment this.
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false

### Package selection
tasksel tasksel/first multiselect standard, ssh-server
d-i pkgsel/include string openssh-server sudo bzip2 acpid cryptsetup zlib1g-dev wget curl dkms fuse make nfs-common net-tools cifs-utils rsync dosfstools
d-i pkgsel/install-language-support boolean false

# Do not scan additional CDs
apt-cdrom-setup apt-setup/cdrom/set-first boolean false

# Use network mirror
apt-mirror-setup apt-setup/use_mirror boolean true

popularity-contest popularity-contest/participate boolean true

# Select base install
tasksel tasksel/first multiselect standard, ssh-server

# This is fairly safe to set, it makes grub install automatically to the MBR
# if no other operating system is detected on the machine.
d-i grub-installer/only_debian boolean true

# This one makes grub-installer install to the MBR if it also finds some other
# OS, which is less safe as it might not be able to boot that other OS.
d-i grub-installer/with_other_os boolean true


# allow image to boot without nvram - mandatory for packer images
d-i grub-installer/force-efi-extra-removable boolean true

d-i preseed/early_command string echo "$(debconf-get preseed/url)" > /var/run/preseed.last_location ; \
        umount /media

d-i preseed/late_command string in-target mkdir -p /home/geoff/.ssh; \
in-target sed -i '/^deb cdrom:/s/^/#/' /etc/apt/sources.list; \
in-target sed -i '/^%sudo/c%sudo ALL=(ALL) NOPASSWD:ALL' /etc/sudoers; \
in-target /bin/sh -c "echo 'ssh-rsa PUTYOURSSHPUBLICKEYHEREFOREASYACCESS' >> /home/geoff/.ssh/authorized_keys"; \
in-target /bin/sh -c "echo 'ssh-rsa PUTYOURSSHPUBLICKEYHEREFOREASYACCESS' >> /home/geoff/.ssh/authorized_keys"; \
in-target chown -R geoff:geoff /home/geoff/.ssh/; \
in-target chmod 644 /home/geoff/.ssh/authorized_keys; \
in-target chmod 700 /home/geoff/.ssh/

# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note
d-i debian-installer/exit/poweroff boolean true

Example grub.cfg

This was also necessary for my environment to enable preseed.cfg on one of the menu entries. It had to be copied to /mnt/data/boot/grub/grub.cfg

set default="2>5"
set timeout=10
if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
   font=$prefix/font.pf2
fi

if loadfont $font ; then
  set gfxmode=800x600
  set gfxpayload=keep
  insmod efi_gop
  insmod efi_uga
  insmod video_bochs
  insmod video_cirrus
  insmod gfxterm
  insmod png
  terminal_output gfxterm
fi

if background_image /isolinux/splash.png; then
  set color_normal=light-gray/black
  set color_highlight=white/black
elif background_image /splash.png; then
  set color_normal=light-gray/black
  set color_highlight=white/black
else
  set menu_color_normal=cyan/blue
  set menu_color_highlight=white/blue
fi

insmod play
play 960 440 1 0 4 440 1
set theme=/boot/grub/theme/1
menuentry --hotkey=g 'Graphical install' {
    set background_color=black
    linux    /install.amd/vmlinuz vga=788 --- quiet
    initrd   /install.amd/gtk/initrd.gz
}
menuentry --hotkey=i 'Install' {
    set background_color=black
    linux    /install.amd/vmlinuz vga=788 --- quiet
    initrd   /install.amd/initrd.gz
}
submenu --hotkey=a 'Advanced options ...' {
    set menu_color_normal=cyan/blue
    set menu_color_highlight=white/blue
    set theme=/boot/grub/theme/1-1
    set gfxpayload=keep
    menuentry '... Graphical expert install' {
        set background_color=black
        linux    /install.amd/vmlinuz priority=low vga=788 ---
        initrd   /install.amd/gtk/initrd.gz
    }
    menuentry '... Graphical rescue mode' {
        set background_color=black
        linux    /install.amd/vmlinuz vga=788 rescue/enable=true --- quiet
        initrd   /install.amd/gtk/initrd.gz
    }
    menuentry '... Graphical automated install' {
        set background_color=black
        linux    /install.amd/vmlinuz auto=true priority=critical vga=788 --- quiet
        initrd   /install.amd/gtk/initrd.gz
    }
    menuentry --hotkey=x '... Expert install' {
        set background_color=black
        linux    /install.amd/vmlinuz priority=low vga=788 ---
        initrd   /install.amd/initrd.gz
    }
    menuentry --hotkey=r '... Rescue mode' {
        set background_color=black
        linux    /install.amd/vmlinuz vga=788 rescue/enable=true --- quiet
        initrd   /install.amd/initrd.gz
    }
    menuentry --hotkey=a '... Automated install' {
        set background_color=black
        linux    /install.amd/vmlinuz auto=true priority=critical vga=788 DEBCONF_DEBUG=5 preseed/file=/cdrom/preseed.cfg --- text
        initrd   /install.amd/initrd.gz
    }
    submenu --hotkey=s '... Speech-enabled advanced options ...' {
        set menu_color_normal=cyan/blue
        set menu_color_highlight=white/blue
        set theme=/boot/grub/theme/1-1-1
        set gfxpayload=keep
        menuentry --hotkey=x '... Expert speech install' {
            set background_color=black
            linux    /install.amd/vmlinuz priority=low vga=788 speakup.synth=soft ---
            initrd   /install.amd/gtk/initrd.gz
        }
        menuentry --hotkey=r '... Rescue speech mode' {
            set background_color=black
            linux    /install.amd/vmlinuz vga=788 rescue/enable=true speakup.synth=soft --- quiet
            initrd   /install.amd/gtk/initrd.gz
        }
        menuentry --hotkey=a '... Automated speech install' {
            set background_color=black
            linux    /install.amd/vmlinuz auto=true priority=critical vga=788 speakup.synth=soft --- quiet
            initrd   /install.amd/gtk/initrd.gz
        }
    }
}
submenu --hotkey=d 'Accessible dark contrast installer menu ...' {
    set menu_color_normal=white/black
    set menu_color_highlight=yellow/black
    set color_normal=white/black
    set color_highlight=yellow/black
    background_image
    set theme=/boot/grub/theme/dark-1-2
    set gfxpayload=keep
    menuentry --hotkey=g '... Graphical install' {
        set background_color=black
        linux    /install.amd/vmlinuz vga=788 theme=dark --- quiet
        initrd   /install.amd/gtk/initrd.gz
    }
    menuentry --hotkey=i '... Install' {
        set background_color=black
        linux    /install.amd/vmlinuz vga=788 theme=dark --- quiet
        initrd   /install.amd/initrd.gz
    }
    submenu --hotkey=a '... Advanced options ...' {
        set menu_color_normal=white/black
        set menu_color_highlight=yellow/black
        set color_normal=white/black
        set color_highlight=yellow/black
        background_image
        set theme=/boot/grub/theme/dark-1-2-1
        set gfxpayload=keep
        menuentry '... Graphical expert install' {
            set background_color=black
            linux    /install.amd/vmlinuz priority=low vga=788 theme=dark ---
            initrd   /install.amd/gtk/initrd.gz
        }
        menuentry '... Graphical rescue mode' {
            set background_color=black
            linux    /install.amd/vmlinuz vga=788 rescue/enable=true theme=dark --- quiet
            initrd   /install.amd/gtk/initrd.gz
        }
        menuentry '... Graphical automated install' {
            set background_color=black
            linux    /install.amd/vmlinuz auto=true priority=critical vga=788 theme=dark --- quiet
            initrd   /install.amd/gtk/initrd.gz
        }
        menuentry --hotkey=x '... Expert install' {
            set background_color=black
            linux    /install.amd/vmlinuz priority=low vga=788 theme=dark ---
            initrd   /install.amd/initrd.gz
        }
        menuentry --hotkey=r '... Rescue mode' {
            set background_color=black
            linux    /install.amd/vmlinuz vga=788 rescue/enable=true theme=dark --- quiet
            initrd   /install.amd/initrd.gz
        }
        menuentry --hotkey=a '... Automated install' {
            set background_color=black
            linux    /install.amd/vmlinuz auto=true priority=critical vga=788 theme=dark --- quiet
            initrd   /install.amd/initrd.gz
        }
    }
}
menuentry --hotkey=s 'Install with speech synthesis' {
    set background_color=black
    linux    /install.amd/vmlinuz vga=788 speakup.synth=soft --- quiet
    initrd   /install.amd/gtk/initrd.gz
}

Post comment

Markdown is allowed, HTML is not. All comments are moderated.