In this day and age of cloud computing, installing an image from scratch is something that is probably not needed very often, if at all, and probably something that is only needed if installing a hardware machine. Major Linux vendors offer cloud versions of their images, such as Ubuntu and CentOS. Using these images with a compatible system ensures that one can get started up on a fresh Linux install very quickly, be it with a Public cloud like EC2, an OpenStack infrastructure, or even just a basic KVM host.
However, if it’s desired to use some of these images in a non-cloud setup, such as the latter scenario, there are some things that need to be done. I will be using the CentOS images as an example.
Step 1 – Resetting the Root Password
After the image has been downloaded and added into KVM, the root password needs to be reset.
This is actually a refresh of an age-old trick to get into Linux systems. Before, it was easy enough as adding init=/bin/bash
to the end of the kernel parameter in GRUB, but times have changed a bit. This method actually still works, but just needs a couple of additions to get it to go. Read on below.
A note – SELinux
SELinux is enabled on the CentOS cloud images. The steps below include disabling it when the root password is reset. Make sure this is done, or you will have a bad time. Note that method #1 also includes enforcing=0
as a boot parameter, so if the this is missed, you have an opportunity to do in the current boot session before the system is rebooted.
Method #1 – “graceful” thru rd.break
This is the Red Hat supported method as per the manual.
rd.break
stops the system just before the hand-off to the ramdisk. There are some situations where this can cause issues, but this is rare, and a cloud image is far from it.
Reboot the system, and abort the GRUB menu timeout by mashing arrow keys as soon as the boot prompt comes up. Then, select the default option (usually the top, the latest non-rescue kernel option) and press “e” to edit the parameters.
Make sure the only parameters on the linux
or linux16
line are:
- The path to the kernel (should be the first option, probably referencing the
/boot
directory) - The path or ID for the root filesystem (the
root=
option) - The
ro
option
Then, supply rd.break enforcing=0
option at the end. Press Ctrl-X to boot.
This will boot the system into an emergency shell that does not require a password, right before when the system would normally have handed it off to the ramdisk.
When the system is in the rescue state like this, the system is mounted on /sysroot
. As such, a few extra steps are required to get the system mounted so that the password can be reset properly. Run:
mount -o remount,rw /sysroot chroot /sysroot passwd root [change password here] vi /etc/sysconfig/selinux [set SELINUX=disabled] exit mount -o remount,ro /sysroot exit
This load /sysroot
into a chroot shell. The password will be prompted for on the passwd root
line. Also, make sure to edit /etc/sysconfig/selinux
and set SELINUX=disabled
. After both of these are done, exit the shell, re-mount the filesystem read-only again to flush any writes, and exit
the emergency shell. The system will either now reboot or just resume booting.
Method #2 – old-school init=/bin/bash
init=/bin/bash
still works, funny enough, but there are some options that need to be removed on the CentOS system, as mentioned in method #1.
Reboot the system, and abort the GRUB menu timeout by mashing arrow keys as soon as the boot prompt comes up. Then, select the default option (usually the top, the latest non-rescue kernel option) and press “e” to edit the parameters.
Make sure the only parameters on the linux
or linux16
line are:
- The path to the kernel (should be the first option, probably referencing the
/boot
directory) - The path or ID for the root filesystem (the
root=
option) - The
ro
option
Then, supply the init=/bin/bash
option at the end. Press Ctrl-X to boot.
After the initial boot the system is tossed into a root shell. Unlike method #1, this shell is already in the system, and /
is the root, without a chroot being necessary. Simply run the following:
mount -o remount,rw / passwd root [change password here] vi /etc/sysconfig/selinux [set SELINUX=disabled] mount -o remount,ro /
The password will be prompted on the passwd root
command. Also, make sure to edit /etc/sysconfig/selinux
and set SELINUX=disabled
. After both of these are done, the filesystem should be remounted read-only to ensure that all writes are flushed. From here, simply reboot through a hard reset or ctrl-alt-del
.
Last Few Steps
Now that the system can be rebooted and logged into, There are a few final steps:
Remove cloud-init
This is probably spamming the console right about now. Go ahead and disable it.
systemctl stop cloud-init.service yum -y remove cloud-init
Enable password authentication
Edit /etc/ssh/sshd_config
and change PasswordAuthentication
to yes
. Make sure the line that is not commented out is changed. Then restart SSH:
systemctl restart sshd.service
The cloud image should now be ready for general use.
Honorable Mention – Packer
All of this is not to say tools like Packer don’t have great merit in image creation, and in fact if you wanted to build a generic image for KVM, rather than just grabbing one like I mention above, there is a qemu builder that can do just that. Doing this will also ensure that the image lacks the cloud-init tools and what not that you may not need in your application.