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:
- Prepare USB stick
- Loopback mount installer ISO
- Copy to USB
- Copy
preseed.cfg
and related files to USB - 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
}