This is a preseed file for Debian 12 (“Bookworm”), set up for a minimal server installation that can be used as a basis to build on.
This is a work in progress, and is subject to updates.
Please don’t rely on this for anything important without reviewing it to make sure it matches your needs.
The easiest way to use this preseed file is if you have a HTTP (not HTTPS) server reachable from the system on which you are installing Debian, because that allows you to use official media to start the installation process. Although not a hard requirement, the process becomes easier if you make the file available at the default path /d-i/bookworm/preseed.cfg
. Note that in any case, the file must be served as plain text (not embedded in a web page) and must start with the #_preseed_V1
preamble.
The root
password after installation is trivial
.
The comments in the file refer to each relevant section in the Debian Bookworm installation guide.
Known issues
- For some reason,
/etc/apt/sources.list
does not get populated as intended during the installation process. This is worked around in thelate_command
which is executed as the installation finishes. - The system hostname after installation is the generic
debian
.
Trade-offs
- The
root
password is static and in plain text within the preseed configuration. Storing a password hash in the preseed file I publish here would not meaningfully increase security, since I would need to state theroot
password anyway. (It does however get hashed normally before being stored in the newly installed system’s/etc/shadow
.) Change theroot
password immediately after installation and/or replace the one in the file with one you generate yourself. - Creation of an unprivileged account during the installation process is disabled. This is deliberate; create such accounts on an as-needed basis after the installation finishes, ideally through whatever configuration management system you are using.
- The installed system does not use LVM or LUKS. This is deliberate; this is intended to be for effectively a throwaway installation with nothing on it that is important to keep (a “cattle”, not pet, installation). You can provision the disk with space to spare and/or add more disk or network storage later to mount at relevant mointpoints such as
/home
,/srv
or/var/mail
. - It would be cleaner to fetch configuration files over the network or from separate media rather than rewriting them based on embedded data in the
late_command
. However, the current approach makes the preseed configuration self-contained.
Creating a KVM virtual machine
To create a virtual machine and use this to install Debian 12, you can use something similar to:
$ virt-install --connect qemu:///system --memory memory=1024 --sysinfo emulate --vcpus 1 --cpu host --clock offset=utc --boot hd --network network=default,model=virtio --graphics spice --autoconsole graphical --video qxl --cdrom /var/lib/libvirt/images/debian-12.0.0-amd64-DVD-1.iso --name debian12-$(date +%Y%m%d-%H%M%S)-$$-$(printf '%04x' $RANDOM) --disk pool=default,size=5,bus=virtio,format=raw --osinfo name=debian12
The most likely initial points of customization of the above is the values to --connect
(virtualization instance to use), --cdrom
(path to the installation DVD ISO image), --name
(the name of the VM to be created), and --disk
(particularly pool
, size
and format
). Note that for clarity, this explicitly specifies some values which are currently defaults. Depending on how recent your host system is, you may need to use something like --osinfo name=debian11
or --osinfo name=linux2022
instead.
The installer will complain about low memory if given less than 1024 MiB RAM, and seems to fail to detect the virtualized network hardware if given less than 480 MiB. The RAM allocation can be reduced after installation; I was able to successfully boot the installed system down to 246 MiB RAM, but not when reducing the RAM allocation further, so 256 MiB is probably a reasonable minimum allocation after installation. 256 MiB also happens to be the listed minimum RAM requirement for Debian 12, so pressing below that, you’re on your own.
The disk needs to be at least 3 GiB for successful installation, although after the installation it only holds about 1 GiB of files (plus a swap partition). If you use something other than bus=virtio
, you may need to adjust /dev/vda
in the preseed file accordingly. The preseed file sets up a single /
file system (including /boot
, /home
and /usr
), plus swap; you can add more disk normally later. To allow some extra space during upgrades and such, I suggest allocating at least 5 GiB for any VMs that you intend to keep around for any real length of time.
Starting the installation
To start the installation:
- Boot from the installation media
- Once at the GRUB menu and before the countdown timer expires, press Escape
- At the
boot:
prompt, typeauto url=fqdn.example
and press Enter
You can also provide a full URL such as http://fqdn.example/bookworm-preseed.cfg
. Note that at this point in the boot process, the keyboard layout is very likely US English.
If you select the “Automated” installation option in the menu, the installer will prompt for the preseed file’s location.
Once you get past the boot:
prompt and especially once you see the progress dialogs flashing past, the process should be 100% hands-off and you can disconnect that viewer session. The VM will power off once installation is complete; simply power it back on to start using the VM. (virt-install
will automatically power the VM back on when it powers off if the viewer session is still active.)
Upon boot, for convenience, the system’s IPv4 and IPv6 addresses will be printed on the console at the login prompt. If you don’t want that, delete /etc/issue.d/ip-addresses.issue
.
After the installation finishes, password-based login for root
is enabled for SSH. To revert to the normal behavior, after you have either set up some other means of authentication for root
logins or set up an unprivileged account with sudo
access, delete /etc/ssh/sshd_config.d/permit-root-login.conf
and run systemctl restart sshd.service
.
bookworm/preseed.cfg
The most likely points of customization is everything under B.4.1 Localization; under B.4.4 Mirror settings d-i mirror/http/hostname
; and under B.5.1 Running custom commands the /etc/apt/sources.list
URLs. Also under B.4.5 Account setup you may want to customize the root
password (or just log in and change it immediately after installation).
#_preseed_V1 # B.4.1. Localization d-i debian-installer/language string en d-i debian-installer/country string SE d-i debian-installer/locale string en_US.UTF-8 d-i keyboard-configuration/xkb-keymap select se # B.4.2. Network configuration # B.4.3. Network console # B.4.4. Mirror settings d-i mirror/protocol string http d-i mirror/country string manual d-i mirror/http/hostname string ftp.us.debian.org d-i mirror/http/directory string /debian d-i mirror/http/proxy string d-i mirror/suite string bookworm # B.4.5. Account setup d-i passwd/root-login boolean true d-i passwd/make-user boolean false d-i passwd/root-password password trivial d-i passwd/root-password-again password trivial # B.4.6. Clock and time zone setup d-i clock-setup/utc boolean true d-i time/zone string Etc/UTC d-i clock-setup/ntp boolean true d-i clock-setup/ntp-server string debian.pool.ntp.org # B.4.7. Partitioning d-i partman-auto/disk string /dev/vda d-i partman-auto/method string regular d-i partman-auto/choose_recipe select atomic 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 # B.4.7.3. Controlling how partitions are mounted d-i partman/mount_style select uuid # B.4.8. Base system installation d-i base-installer/kernel/image string linux-image-amd64 # B.4.9. Apt setup d-i apt-setup/non-free-firmware boolean false d-i apt-setup/non-free boolean false d-i apt-setup/contrib boolean false d-i apt-setup/disable-cdrom-entries boolean true d-i apt-setup/services-select multiselect security, updates d-i apt-setup/security_host string security.debian.org d-i debian-installer/allow_unauthenticated boolean false # B.4.10. Package selection tasksel tasksel/first multiselect standard, ssh-server d-i pkgsel/upgrade select full-upgrade popularity-contest popularity-contest/participate boolean false # B.4.11. Boot loader installation d-i grub-installer/only_debian boolean true d-i grub-installer/bootdev string /dev/vda # B.4.12. Finishing up the installation d-i finish-install/reboot_in_progress note d-i cdrom-detect/eject boolean true # B.4.13. Preseeding other packages # B.5.1. Running custom commands during the installation d-i preseed/late_command string \ in-target apt-get -y purge installation-report; \ \ >>/target/etc/apt/sources.list echo deb http://ftp.us.debian.org/debian bookworm main; \ >>/target/etc/apt/sources.list echo deb http://deb.debian.org/debian-security/ bookworm-security main; \ >>/target/etc/apt/sources.list echo deb http://ftp.us.debian.org/debian bookworm-updates main; \ in-target apt-get update; \ in-target apt-get -y dist-upgrade; \ \ mkdir -p /target/etc/issue.d; \ >>/target/etc/issue.d/ip-addresses.issue echo \\4 \\6; \ >>/target/etc/issue.d/ip-addresses.issue echo; \ \ >/target/etc/nftables.conf echo \#!/usr/sbin/nft -f; \ >>/target/etc/nftables.conf echo flush ruleset; \ >>/target/etc/nftables.conf echo table inet filter {; \ >>/target/etc/nftables.conf echo chain input {; \ >>/target/etc/nftables.conf echo type filter hook input priority filter; \ >>/target/etc/nftables.conf echo policy drop; \ >>/target/etc/nftables.conf echo ct state established,related accept; \ >>/target/etc/nftables.conf echo iifname lo accept; \ >>/target/etc/nftables.conf echo ip protocol icmp accept; \ >>/target/etc/nftables.conf echo ip6 nexthdr icmpv6 accept; \ >>/target/etc/nftables.conf echo ip6 nexthdr ipv6-icmp accept; \ >>/target/etc/nftables.conf echo tcp dport 22 accept; \ >>/target/etc/nftables.conf echo }; \ >>/target/etc/nftables.conf echo chain forward {; \ >>/target/etc/nftables.conf echo type filter hook forward priority filter; \ >>/target/etc/nftables.conf echo policy accept; \ >>/target/etc/nftables.conf echo }; \ >>/target/etc/nftables.conf echo chain output {; \ >>/target/etc/nftables.conf echo type filter hook output priority filter; \ >>/target/etc/nftables.conf echo policy accept; \ >>/target/etc/nftables.conf echo }; \ >>/target/etc/nftables.conf echo }; \ in-target chmod 700 /etc/nftables.conf; \ in-target chown root:root /etc/nftables.conf; \ in-target systemctl enable nftables.service; \ \ mkdir -p /target/etc/ssh/sshd_config.d; \ >>/target/etc/ssh/sshd_config.d/permit-root-login.conf echo PermitRootLogin yes;