So we had a specific use case where we wanted to be able to set up Linux VMs on a Windows Hyper-V hypervisor, without any additional services apart from:
I should also mention that we didn't have the usual network services like DHCP, etc.
That being said, we needed to be able to launch a VM on the hypervisor that would perform an unattended installation using an Ubuntu ISO installer image, pushed to the hypervisor from the deployment computer.
The expected result is a fully configured VM with all parameters set, either generic (like maybe keyboard layout) or specific (like its hostname, network configuration including IP addresses, disk partitioning, etc).
We first tried to use the old unattended installer that is based on preseed files. I am calling it old because It dates back to the creation of Debian-based distros over a decade ago, and did not evolve all that much in recent years. It's also the only one we knew when we started this thing. So that's naturally the one we tried to use first.
This system is based on the fact that every question that is asked during the installation can be answered by a line in the file called "preseed".
The preseed file uses a very simple syntax:
# Notes
# - d-i stands for "debian installer"
d-i <section> <answer_type> <answer_value>
So, what exactly happens when you start a new installation with this installer? Well, it basically skips all question prompts it already has the answers to in your preseed file.
An unattended installation is then just an installation that started with a preseed file that already contained all answers that are required during the installation process.
The installer can get a preseed file from within the installer ISO image, or from the network using the HTTP protocol.
We faced a few problems when we tried to set up our unattended installation with the preseed system.
First, the answers you need to give are not well documented, or at least the documentation is in my opinion quite hard to understand for people that are not fully acquainted with these kinds of tools. Also, the debugging process is long and painful since you can see configuration errors only by trying to install your OS from scratch each time. A spelling mistake in a section of the file will cause the installer to prompt the question anyway, without telling you the mistake you made. So debugging can be a long frustrating process in my experience.
In the end, it's just a question of patience, and you should get through anyway.
The real problem we had in our case, which made us look for another solution, was that we didn't succeed in giving the preseed file to the installer in the first place.
Indeed, as mentioned above, we knew only two ways to do this:
Unfortunately, none of these were acceptable in our case, since:
We tried to give the preseed to the installer using a small ISO attached as an additional device to the VM, that the installer would have to mount and use dynamically. But we couldn't make this work.
Maybe because it is not possible, or because we just didn’t find the proper way to do it.
Anyway, the fact is that we spent quite some time trying to do it and in the end, it didn't work and we had no idea how to make it work.
That's when we found a mention of a cloud-init-like unattended installation for Ubuntu servers in Packer's documentation: Subiquity.
If you do not explicitly search for "Subiquity" or "Ubuntu 20.04 server" on the Internet, chances are you will never find anything about it. And it would be a shame because it's really a great tool, that is really easy to understand and to set up!
One of the things that can be annoying with preseed is when it bothers us with the keyboard layout (because we cannot manage to find the proper syntax to fill in this question in the preseed file) when we seldom really care for this on a server installation. Or maybe that's something we can deal with later with another tool like Ansible.
Well, Subiquity has the good property to use default properties silently in most cases.
Subiquity’s config is described in yaml files, which are more structured and understandable than preseeds.
Subiquity uses cloud-init
(or at least some part of it) in order to get and compute this config. This means that the concepts you may already know about cloud-init will help you a lot to make your way through giving your configuration to Subiquity.
And since cloud-init is more and more used nowadays, that's a pretty good advantage I think😀
I'm not sure whether curtin
is a well-known tool. What I do know, is that it works well and can take care of the partitioning part for you and support LVM.
With preseeds, you can specify partitioning options, and optionally use the Debian recipes syntax. When well set up it works fine. But making it work when you don't know it at all is definitely more complicated.
With Subiquity, you can use a simple yaml syntax that is then given to curtin during the installation.
So Subiquity is a great tool, easy to understand. Yet, there is always room for perfection.
At the time we tried it we saw the following, minor limitations:
So now, let's just come back to our initial use case.
With Subiquity, we implemented it very quickly by:
user-data
, with the ci-data
label ("cloud-init data")What happens next is that during the installation, the cloud-init tooling will look up many data sources, and will find our ISO with the label ci-data on it.
It will mount it and process our configuration. Finally, it will run the installation fully.
So we didn't need any external service to give the installation process our configuration. It was pretty straightforward. And furthermore, the config we needed was so easy to describe using Subiquity that we didn't really feel the drawback of switching to a new tool and needing to learn how to use it.
I hope you will find this story about how we ran into Subiquity and what benefits it can bring you interesting. I won't say this tool is objectively better than others. What I can say, however, is that it enabled us to reach our goal easily and quickly, and it gave us a comforting feeling of control over what we were doing.