I needed to install CentOS 7 on an embedded PC with UEFI and 2 SSD disks in mdadm RAID1.
While I’m sure the guys at Red Hat work very hard on CentOS, the installer is a piece of cr*p, especially when it comes to disk partitioning. I have never hated any installer more than the CentOS disk partitioner. I don’t know what happened. The disk partitioning tool in CentOS 6 installer was fine, I had no problems using it, but in the 7 installer it’s just a nightmare to do anything. In my opinion Windows installer does a better job of disk partitioning than the CentOS 7 installer.
While many people who like CentOS will proclaim that the error is between the keyboard and chair, I welcome them to provide a write-up and screenshots of how to accomplish my desired partitioning scheme using the graphical installer. If the instructions are shorter than this blog post, next time I won’t use a chroot to install.
I loosely based my method off of this post, but immediately found I had to deviate because I didn’t have USB install media with all the required commands on it.
Required tools:
1) USB stick with some Linux distro on it (I prefer the Gentoo minimal installer, it’s small and it includes lots of useful utilities)
2) USB stick with the CentOS minimal installer on it
3) About 2GB of free space, you can use a ramdisk, or create an extra partition using the free space on the USB sticks (CentOS occupies about 800MB, Gentoo about 300MB)
Steps:
1) Boot the Gentoo installer off the USB stick
2) Partition your disks however you like using gdisk, fdisk, or parted
3) Create your mdadm array(s)
4) Plug in the CentOS 7 USB stick and mount it to a temporary mount point (e.g. /tmp/centos)
Inside the CentOS USB stick you will find LiveOS/squashfs.img, you need to loopback mount this:
livecd ~ # mount -o loop /tmp/cinstall/LiveOS/squashfs.img /tmp/csquashfs/
Now we have yet another image to mount, this one within the squashfs image:
livecd ~ # mount -o loop /tmp/csquashfs/LiveOS/rootfs.img /tmp/croot
Finally we have a Linux filesystem. But unfortunately we cannot use it for anything as it is mounted read-only and there is no resolv.conf present, so no domain names can be resolved. This is why you need ~2GB of free space somewhere (or 4GB of RAM).
livecd ~ # mkfs -q /dev/ram1 1572864 livecd ~ # mkdir -p /tmp/ramdisk livecd ~ # mount /dev/ram1 /tmp/ramdisk livecd ~ # rsync -avHp /tmp/croot /tmp/ramdisk
Now that we have the installer rootfs somewhere writable, copy /etc/resolv.conf to the filesystem:
livecd ~ # cp /etc/resolv.conf /tmp/ramdisk/etc/resolv.conf
Mount your destination partition for CentOS somewhere you can access from within the chroot:
livecd ~ # mount /dev/vg0/centos /tmp/ramdisk/mnt
Chroot to the installer environment:
livecd ~ # chroot /tmp/ramdisk
Download the CentOS release RPM and install it to the destination partition:
bash-4.2# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-0.1406.el7.centos.2.3.x86_64.rpm bash-4.2# rpm --root=/mnt --nodeps -i centos-release-7-0.1406.el7.centos.2.3.x86_64.rpm
Because yum is missing the yummain module in the installation environment, we need to download and install the yum RPM on the installer partition:
bash-4.2# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/yum-3.4.3-118.el7.centos.noarch.rpm bash-4.2# rpm -i --nodeps yum-3.4.3-118.el7.centos.noarch.rpm
Now finally we can run yum on the destination partition to install CentOS:
bash-4.2# yum --installroot=/mnt update bash-4.2# yum --installroot=/mnt install -y yum bash-4.2# yum --installroot=/mnt install -y @core kernel bash-4.2# yum --installroot=/mnt install -y grub2-efi efibootmgr lvm2 mdadm \ dosfstools kernel
Now unfortunately I hit a small snag: the Gentoo installer isn’t EFI aware. Exit the chroot, but remember to copy /etc/resolv.conf to the destination partition:
livecd ~ # cp /etc/resolv.conf /tmp/ramdisk/mnt/etc/
Poweroff and unplug the Gentoo installer USB stick. Plug in the CentOS installer stick and boot to the rescue environment. Skip rootfs detection.
Mount the partition/LV slice containing your CentOS installation:
sh-4.2# mkdir /mnt/centos sh-4.2# mount /dev/vg0/centos /mnt/centos sh-4.2# mount -t proc proc /mnt/centos/proc sh-4.2# mount --rbind /dev /mnt/centos/dev sh-4.2# mount --rbind /sys /mnt/centos/sys sh-4.2# chroot /mnt/centos /bin/bash
Save the mdadm array information to the mdadm.conf configuration file:
bash-4.2# mdadm --detail --scan > /etc/mdadm.conf
Format your EFI boot partition:
bash-4.2# mkfs.vfat /dev/sda1 bash-4.2# mkdir /boot/efi bash-4.2# mount /dev/sda1 /boot/efi
Install grub:
bash-4.2# grub2-install Installing for x86_64-efi platform ... Installation finished. No error reported.
Now, dear reader, this is the part where you do not see the hours I spent debugging why dracut would not find my root partition (hint: see Fedora wiki for dracut debugging steps). The tl;dr is that the mdadm array wasn’t being assembled, for reasons still unknown. To solve this we need to add our array UUID as an additional kernel parameter for grub:
bash-4.2# MD_UUID=$(mdadm -D /dev/md0 | grep UUID | awk '{print $3}') bash-4.2# grubby --update-kernel=/boot/vmlinuz-3.10.0-123.20.1.el7.x86_64 \ --args="rd_MD_UUID=$MD_UUID" bash-4.2# grub2-mkconfig -o /boot/grub2/grub.cfg
Absolutely verify in /boot/grub2/grub.cfg that the correct rd_MD_UUID was appended to linuxefi, or like me, you may be left wondering why your system won’t boot.
Check with efibootmgr that a menu entry was created:
bash-4.2# efibootmgr -v ... Boot0014* grub HD(1,800,32000,SUPER-LONG-UUID)File(\EFI\grub\grubx64.efi)
Don’t forget to set a root password:
bash-4.2# passwd Changing password for user root. New password: Retype new password: passwd: all authentication tokens updated successfully
Configuring the hostname (using hostnamectl, or editing /etc/sysconfig/network and /etc/hostname), udev rules for eth* interface names, and static network configuration in /etc/sysconfig/network-scripts/ifcfg-eth* is left as an exercise for the reader.
After rebooting
If when you reboot you find that you cannot login as root using the password you specified, it’s probably SELinux. Normally I hate disabling SELinux, but in this case I was so tired of spending a day and a half debugging booting issues, I just disabled it and went on with the setup.
Despite what the wonderful CentOS installer tells you, you do not require a separate /boot partition. Right now this is what the partition layout looks like:
Disk /dev/sda: 128.0 GB, 128035676160 bytes, 250069680 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disk label type: gpt # Start End Size Type Name 1 2048 206847 100M EFI System EFI System 2 206848 250069646 119.1G Linux RAID Linux RAID
Because the contents of /boot/efi is static, and cannot be mdraid, remember to copy the contents of /dev/sda1 to /dev/sdb1 so that if your first drive ever dies, you will still have the required EFI components to boot off the second drive.
Overall, I can’t say this was a lot of fun. But I did learn a lot more about dracut and the CentOS booting process, and I can still say with confidence that I hate the CentOS 7 installer.
I can agree with you on 1 thing, CentOS 7 installer really sucks on big! :))
Two notes:
1. Debian (and likely on Ubuntu, too) the rpm package configuration differs from the default configuration in the database path. Debian package sets rpm’s _dbpath macro to point to ~/.rpmdb instead of the system path /var/lib/rpm. This results in a broken roots chroot in a very non-obvious way, where the surface symptom is that yum update fails, and ultimate symptom is that centos-release is not actually seen as installed within chroot, because rpm within the chroot looks for the db at /var/lib/rpm and finds it as empty (silent, no error, too!), while rpm –root from outside chroot reports packages as installed because it’s looking at chroot/root/.rpmdb created during installation. Tne fix is to revert _dbpath macro to the system path before creating the chroot: create or edit the /etc/rpm/macros with contents “%_dbpath /var/lib/rpm”.
2. For creating the CentOS chroot itself, I found that it is not necessary to manually download and install .rpm packages. it’s sufficient to just do:
sudo yum –installroot=$PWD install -y @core