I wanted to build on the automated deployments for Debian and Mint, etc. and the next logical step is to use a PXE boot server and DHCP. Thankfully someone has already built a container to do just that – ferrarimarco/pxe

Now all I have to do it get my Debian boot image injected into this.


It ended up being pretty straight forward. Setup the docker-compose as follows:

version: '3'

    image: ferrarimarco/pxe
      - ${PWD}/debian-installer/:/var/lib/tftpboot/debian-installer/:ro
      - ${PWD}/additional_menu_entries:/var/lib/tftpboot/pxelinux.cfg/additional_menu_entries:ro
      - ${PWD}/d-i/:/var/lib/tftpboot/d-i:ro
      # - ${PWD}/dnsmasq.d/dnsmasq.conf:/etc/dnsmasq.conf:ro
    network_mode: "host"
      - "dnsmasq"
      - "--no-daemon"
      - "--dhcp-range=,"
      - "--dhcp-broadcast"
      - "--domain=domain.tld"
      - "--dhcp-option=3,"
      - "--dhcp-option=6,"

The --dhcp-broadcast is an important option. Without it it fails to give out an IP address (see https://github.com/ferrarimarco/docker-pxe/pull/21#issuecomment-515686208)

Also edit the dhcp-options to suit your environment.

--dhcp-option=3, # This is your default route
--dhcp-option=6, # This is your DNS server


I then created the file additional_menu_entries and put the boot options for Debian into it.

LABEL debian-10-amd64 Gnome Desktop
  MENU LABEL Debian 10 amd64 Gnome Desktop
  KERNEL /debian-installer/amd64/linux
  APPEND auto=true priority=critical vga=788 initrd=/debian-installer/amd64/initrd.gz DEBCONF_DEBUG=5 url=tftp:// --
LABEL debian-10-amd64 CLI
  MENU LABEL Debian 10 amd64 CLI
  KERNEL /debian-installer/amd64/linux
  APPEND auto=true priority=critical vga=788 initrd=/debian-installer/amd64/initrd.gz DEBCONF_DEBUG=5 url=tftp:// --

This mounts and overwrites the one inside the container.

Next it’s time to grab the files from Debian’s netboot – https://www.debian.org/distrib/netinst#netboot

You’ll want to use an FTP client to pull the whole structure from http://ftp.debian.org/debian/dists/buster/main/installer-amd64/current/images/netboot/debian-installer/amd64/

$ wget -r -nH --cut-dirs=9 http://ftp.debian.org/debian/dists/buster/main/installer-amd64/current/images/netboot/debian-installer/amd64/
$ # Tidy up the amd64 folder
$ find amd64/ -iname 'index.html*' -exec rm {} \;

You can then put the amd64 folder into the debian-installer folder and you’ll have everything you need to boot a Debian install and complete a network install pulling from a mirror.


Adding the preseeding part to this is very straight forward. We need to boot the installer with the options auto=true priority=critical url=tftp:// where the IP address represents the IP address of our docker host (not the container). You’ll see these options are included in the additional_menu_entries shown above.

From my previous post Debian Preseeding you note we could pull the preseed files from a http server. Well we can also pull them from a tftp server – which is exactly what the dnsmasq service provides. All we need to do is create our d-i structure and mount it into the services volume /var/lib/tftpboot/d-i folder. You’ll notice this is in the menu entry above url=tfpt://....

When the client boots using PXE and selects the Gnome or CLI version the Debian install is fully automated – no questions are asked unless they are “critical”. So be wary booting this way as no questions about overwriting your hard drive will be asked. It will overwrite everything with a fresh install as per your preseed.cfg or preseed-cli.cfg files.


In a virtual environment the only question I got asked was about where to install grub. I suspect this is because normally the install would go onto the first disk /dev/sda, but in libvirt/qemu this is /dev/vda.