Somethings about Debian we operators love is the possibility to automate the
installation process with a preseed file.
Another thing we love is Ansible, since it makes our lives much easier.
Usually we use these tools to automate the setup of our server systems. But since servers are just computers, why not apply these tools to the computers we like to spend so much time in front of.
This post is a guide demonstrating a method how to build your own custom autoinstaller.
The Debian Installer
If you’re not familiar with automated Debian installations, here is a little recap about preseeding the Debian installer.
The Preseed File
If you install a Debian system by hand, the installer will ask you a series of
questions about your installation. A preseed file is basically a text file
containing the answers to these questions.
To write a preseed file, download the
example file and
edit it to your needs.
There are three ways to use a preseed file during the installation process: * Including the file in the installation media * Including the file in the installers initrd * Downloading the file from a http-server
Building your own
Testing the Preseed File
Before building an iso image you might like to test and modify your preseed file.
To do so I’d recommend to setup a small http-server serving the preseed.cfg your
With that in place you can setup a virtual machine, attach the Debian-stabele netinstall CD and choose
Advanced Options →
Automated Installation. The
installer will prompt you for the url to fetch the preseed file from.
This way you can modify the file and re-run the installation easily.
After the Installation
Usually, you will perform several tasks after a fresh installation. This may
include system settings, copying dotfiles and installing software. Also, if you
are using Debian on a Laptop/Workstation you may want to upgrade the system from
stable to unstable.
Ansible is the appropriate tool for these postinstall tasks. Since you have just setup a clean debian VM, you can start a ssh-server in it and use Ansible on the host system to setup your machine.
Building the Installation Media
The ultimate goal of this guide ia a iso-image you can dd on a usb-stick and impress your friends how smooth and easy your debian installation goes.
Extracting the Installer’s Filesystem
First you need to unpack the netinstaller’s iso:
mkdir isofs bsdtar -C isofs -xf debian-netinstall.iso
Preparing the playbooks
When upgrading the OS with Ansible, most tasks after the OS-upgrades will fail
due to changes in the python libraries Ansible uses. Therefore the postinstall
playbook must be split into two separate ones. One for the OS upgrade and one for
all other tasks.
Since these playbooks will be run on the freshly installed machine itself, change the
host directives to
To give you an example, here are the playbooks I used:
- name: Setup a working Workstation hosts: localhost tasks: - name: Check for upgrade state stat: path: /.testing register: upgrade_testing - name: change sources.list to testing copy: dest: /etc/apt/sources.list content: | deb http://http.us.debian.org/debian testing main non-free contrib #deb-src http://http.us.debian.org/debian testing main non-free contrib deb http://http.us.debian.org/debian testing-updates main contrib non-free #deb-src http://http.us.debian.org/debian testing-updates main contrib non-free when: not upgrade_testing.stat.exists - name: update OS to testing apt: update_cache: yes upgrade: dist when: not upgrade_testing.stat.exists - name: save upgrade-state copy: dest: /.testing content: " " - name: change sources.list to sid copy: dest: /etc/apt/sources.list content: | deb http://http.us.debian.org/debian sid main non-free contrib #deb-src http://http.us.debian.org/debian sid main non-free contrib - name: update OS to sid apt: update_cache: yes upgrade: dist
- name: Setup a working Workstation hosts: localhost tasks: - name: create getty-override folder file: path: /firstname.lastname@example.org state: directory - name: Setup autologin copy: dest: /email@example.com/override.conf content: | [Service] ExecStart= ExecStart=-/sbin/agetty --autologin vincent --noclear %I $TERM - name: install some software apt: name: - neovim - git - zsh - firefox - thunderbird - awesome - awesome-extra - redshift-gtk - caffeine - keepassx - exa - fzf - ripgrep - pdfgrep - zathura - zathura-pdf-poppler - okular - asciidoctor - pandoc - network-manager - network-manager-gnome - cbatticon - pasystray - pulseaudio - xorg - xss-lock - i3lock - lxterminal state: present - name: create xorg.conf.d file: path: /etc/X11/xorg.conf.d state: directory - name: Setup Keyboard copy: dest: /etc/X11/xorg.conf.d/00-keyboard.conf content: | Section "InputClass" Identifier "system-keyboard" MatchIsKeyboard "on" Option "XkbLayout" "us" Option "XkbModel" "pc104" Option "XkbVariant" "altgr-intl" Option "XkbOptions" "caps:swapescape" EndSection - name: check for zsh installation stat: path: /usr/bin/zsh register: zsh - name: change user shell to zsh user: name: vincent shell: /usr/bin/zsh when: zsh.stat.exists
Create a folder
rootfs that includes the file-structure you want to be present
on the freshly installed system. This might for example look like this:
rootfs ├── home │ └── vincent │ ├── .config │ ├── .gitconfig │ ├── .oh-my-zsh │ ├── .vim │ ├── .vimrc │ ├── .xinitrc │ ├── .zprofile │ └── .zshrc └── root ├── postinstall2.yml └── postinstall.yml
Now let’s create a
.tar archive of this folder structure and add it to the
cp -r rootfs rootfs.tmp sudo chown -R root:root rootfs.tmp sudo chmod 700 rootfs/root sudo tar -C rootfs.tmp -cf postinstall.tar ./ sudo mv postinstall.tar isofs/ sudo rm -r rootfs.tmp
Some modifications have to be made to your
First, you need to add
ansible to the packages to be installed:
# Individual additional packages to install d-i pkgsel/include string ansible
Secondly, you need to add a
preseed/late_command directive that unpacks the tar
d-i preseed/late_command string tar -C /target -xf /cdrom/postinstall.tar; \ in-target chown -R vincent:vincent /home/vincent;
Now the preseed-file has to be added to the installer’s initrd:
chmod +w -R isofs/install.amd gunzip isofs/install.amd/initrd.gz echo preseed.cfg | cpio -H newc -o -A -F isofs/install.amd/initrd gzip isofs/install.amd/initrd chmod -R -w isofs/install.amd
Generating a new Iso Image
After altering the content of the Image we need to re-calculate the checksums:
chmod +w isofs/md5sum.txt cd isofs md5sum `find -follow -type f` > md5sum.txt chmod -w md5sum.txt cd ..
Now we can generate a
sudo genisoimage -quiet -V "preseed-autoinstall" -J -R -r -l -cache-inodes \ -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 \ -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot \ -o preseed-autoinstall.iso isofs isohybrid --uefi preseed-autoinstall.iso
Et violá, we have a
Now, dd it on a flashdrive, boot your workstation from it and let the
autoinstaller do it’s magic.
After the first boot simply run the two playbooks:
sudo ansible-playbook /root/postinstall.yml sudo ansible-playbook /root/postinstall2.yml
Congratulations, you are good to go.