Gentoo on OCI - part 1

Most of this blog has actually been about on-prem stuff, but hey, it is 2024 so let's do something in the cloud. Let's try to put Gentoo Linux on OCI. One way how to achieve that is to export a VM from VirtualBox to OCI. This blog however describes how to change an existing linux VM with Oracle Linux to Gentoo, closely following the Gentoo handbook.

The end result should be Gentoo on a btrfs file system. OpenRC will be used as the init system.

This first part will cover getting a Gentoo system running. Subsequent parts will be dealing with tidying up, and creating a custom image.

Create a VM and an extra block storage

The start is a standard Oracle Linux 8 VM, with an AMD or Intel shape. Make sure to be able to login over ssh.

Then create an extra block storage of 50 GB and attach it to the VM. The extra block storage will be used to park the Oracle Linux OS on.

Inspect the VM

Linux version

[opc@Gentoo ~]$ hostnamectl
   Static hostname: Gentoo
         Icon name: computer-vm
           Chassis: vm
        Machine ID: 5b526e3f9546492b9b69c39b504b5fd1
           Boot ID: 8dfaa293d3794f559183bf49cd34037e
    Virtualization: kvm
  Operating System: Oracle Linux Server 8.9
       CPE OS Name: cpe:/o:oracle:linux:8:9:server
            Kernel: Linux 5.15.0-203.146.5.1.el8uek.x86_64
      Architecture: x86-64

This is a KVM virtualized VM, with Oracle Linx 8.9 on it, and Linux kernel 5.15.

Disk layout:

[opc@Gentoo ~]$ lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
NAME                SIZE TYPE FSTYPE      MOUNTPOINT
sda                46.6G disk
├─sda1              100M part vfat        /boot/efi
├─sda2                1G part xfs         /boot
└─sda3             45.5G part LVM2_member
  ├─ocivolume-root 35.5G lvm  xfs         /
  └─ocivolume-oled   10G lvm  xfs         /var/oled
sdb                  50G disk

The VM is booted using an UEFI boot loader, with a separate boot partition, and LVM as logical volume manager. There are two logical volumes, both formatted with XFS:

  • ocivolume-root: with the OL8 operating system
  • ocivolume-oled: which is used to gather statistics with the PCP package. PCP is only available under OL8, so we do not need to retain it.

Our extra disk shows up as /dev/sdb.

Boot manager

[opc@OL-8 ~]$ ls /boot
config-4.18.0-513.11.0.1.el8_9.x86_64                    loader
config-5.15.0-203.146.5.1.el8uek.x86_64                  symvers-4.18.0-513.11.0.1.el8_9.x86_64.gz
efi                                                      symvers-5.15.0-203.146.5.1.el8uek.x86_64.gz
grub2                                                    System.map-4.18.0-513.11.0.1.el8_9.x86_64
initramfs-0-rescue-c5779a24a7110341165b3f6f2fbec14a.img  System.map-5.15.0-203.146.5.1.el8uek.x86_64
initramfs-4.18.0-513.11.0.1.el8_9.x86_64.img             vmlinuz-0-rescue-c5779a24a7110341165b3f6f2fbec14a
initramfs-5.15.0-203.146.5.1.el8uek.x86_64.img           vmlinuz-4.18.0-513.11.0.1.el8_9.x86_64
initramfs-5.15.0-203.146.5.1.el8uek.x86_64kdump.img      vmlinuz-5.15.0-203.146.5.1.el8uek.x86_64

The boot manager is GRUB (2), the current version 2, not the old legacy version using an initramfs.

Move Oracle Linux to the additional block volume

All this work needs to be done as root.

Since OL8 is placed on a LVM, it is quite easy to move it to the extra block volume:

[root@Gentoo opc]# fdisk /dev/sdb
[root@Gentoo opc]# vgextend ocivolume /dev/sdb
[root@Gentoo opc]# time pvmove /dev/sda3
  /dev/sda3: Moved: 0.05%
  /dev/sda3: Moved: 0.89%
  ..
  ..
  /dev/sda3: Moved: 99.01%
  /dev/sda3: Moved: 99.77%

real    33m22.695s
user    0m0.086s
sys     0m0.073s

[root@Gentoo opc]# vgreduce ocivolume /dev/sda3
  Removed "/dev/sda3" from volume group "ocivolume"
[root@Gentoo opc]# pvremove /dev/sda3
  Labels on physical volume "/dev/sda3" successfully wiped.

[root@Gentoo opc]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sdb
  VG Name               ocivolume
  PV Size               50.00 GiB / not usable 4.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              12799
  Free PE               1158
  Allocated PE          11641
  PV UUID               iUXGmX-Njij-cVWt-wqjR-Y6Nl-xLxd-L0kKi7

Reformat the root disk

There is now 45 GB on /dev/sda3 for the Gentoo rootfs. OL-8 has a swapfile on XFS formatted the root file system. Swapfiles are not well supported on btrfs; it may be better to allocate a disk partition for this purpose:

[root@Gentoo opc]# fdisk /dev/sda
Command (m for help): p
Disk /dev/sda: 46.6 GiB, 50010783744 bytes, 97677312 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 1048576 bytes
Disklabel type: gpt
Disk identifier: 3A87099A-673A-4D5E-9C66-9D307A1A0FBF

Device       Start      End  Sectors  Size Type
/dev/sda1     2048   206847   204800  100M EFI System
/dev/sda2   206848  2303999  2097152    1G Linux filesystem
/dev/sda3  2304000 97675263 95371264 45.5G Linux LVM

Command (m for help): d
Partition number (1-3, default 3):

Partition 3 has been deleted.

Command (m for help): n
Partition number (3-128, default 3):
First sector (2304000-97677278, default 2304000):
Last sector, +sectors or +size{K,M,G,T,P} (2304000-97677278, default 97677278): +8G

Created a new partition 3 of type 'Linux filesystem' and of size 8 GiB.

Command (m for help): t
Partition number (1-3, default 3):
Partition type (type L to list all types): 19

Changed type of partition 'Linux filesystem' to 'Linux swap'.

Command (m for help): n
Partition number (4-128, default 4):
First sector (19081216-97677278, default 19081216):
Last sector, +sectors or +size{K,M,G,T,P} (19081216-97677278, default 97677278):

Created a new partition 4 of type 'Linux filesystem' and of size 37.5 GiB.

Command (m for help): p
Disk /dev/sda: 46.6 GiB, 50010783744 bytes, 97677312 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 1048576 bytes
Disklabel type: gpt
Disk identifier: 3A87099A-673A-4D5E-9C66-9D307A1A0FBF

Device        Start      End  Sectors  Size Type
/dev/sda1      2048   206847   204800  100M EFI System
/dev/sda2    206848  2303999  2097152    1G Linux filesystem
/dev/sda3   2304000 19081215 16777216    8G Linux swap
/dev/sda4  19081216 97677278 78596063 37.5G Linux filesystem

Command (m for help): w
The partition table has been altered.
Syncing disks.

Format and mount the swap and Gentoo partiton.

[root@Gentoo opc]# mkswap -L swap-sda3 /dev/sda3
[root@Gentoo opc]# swapon /dev/sda3
[root@Gentoo opc]# mkfs -t btrfs -L rootfs /dev/sda4
[root@Gentoo opc]# mkdir /mnt/rootfs /mnt/gentoo
[root@Gentoo opc]# mount /dev/sda4 /mnt/rootfs
[root@Gentoo opc]# btrfs subvol create /mnt/rootfs/gentoo
[root@Gentoo opc]# mount -o subvol=gentoo /dev/sda4 /mnt/gentoo
[root@Gentoo opc]# btrfs subvol create /mnt/rootfs/home

The result is that btrfs subvolume 'gentoo' on the /dev/sda41 partition is mounted on /mnt/gentoo, just like the Gentoo handbook prescribes. The complete partition is mounted on /mnt/rootfs too.

Install Gentoo

The starting point in the handbook would be the chapter 'the stage file'.

[root@Gentoo opc]# cd /mnt/gentoo
[root@Gentoo gentoo]# wget https://distfiles.gentoo.org/releases/amd64/autobuilds/20240329T230405Z/stage3-amd64-openrc-20240329T230405Z.tar.xz
[root@Gentoo gentoo]# tar xpf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner

Add the following to /mnt/gentoo/etc/portage/make.conf:

GRUB_PLATFORMS="efi-64"
ACCEPT_LICENSE="* -@EULA"
FEATURES="parallel-fetch clean-logs"
EMERGE_DEFAULT_OPTS="--jobs=4 --load-average=11"
MAKEOPTS="-j8"

Adjust MAKEOPTS according to the number of OCPUs, memory, and storage available.

Copy some configuration files

These will need to be updated later, but already gives a good starting point:

[root@Gentoo opc]# cp /etc/fstab /mnt/gentoo/etc
[root@Gentoo opc]# cp /etc/default/grub /mnt/gentoo/etc/default/

Chroot into the Gentoo environment

[root@Gentoo gentoo]# cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
[root@Gentoo gentoo]# mount --types proc /proc /mnt/gentoo/proc
[root@Gentoo gentoo]# mount --rbind /sys /mnt/gentoo/sys
[root@Gentoo gentoo]# mount --rbind /dev /mnt/gentoo/dev
[root@Gentoo gentoo]# mount --bind /run /mnt/gentoo/run
[root@Gentoo gentoo]# chroot /mnt/gentoo /bin/bash
Gentoo / # source /etc/profile
Gentoo / # export PS1="(chroot) ${PS1}"

Repositories

(chroot) Gentoo / # mkdir --parents /etc/portage/repos.conf
(chroot) Gentoo / # cp /usr/share/portage/config/repos.conf /etc/portage/repos.conf/gentoo.conf
(chroot) Gentoo / # emerge-webrsync
(chroot) Gentoo / # eselect news read

Timezone

(chroot) Gentoo / # echo "Europe/Amsterdam" > /etc/timezone
(chroot) Gentoo / # emerge --config sys-libs/timezone-data

Locales

(chroot) Gentoo / #  cat > /etc/locale.gen << AA
en_US ISO-8859-1
en_US.UTF-8 UTF-8
de_DE ISO-8859-1
de_DE.UTF-8 UTF-8
nl_NL ISO-8859-1
nl_NL.UTF-8 UTF-8
AA
(chroot) Gentoo / # locale-gen
 * Generating 7 locales (this might take a while) with 12 jobs
 *  (3/7) Generating en_US.ISO-8859-1 ...                               [ ok ]
 *  (1/7) Generating de_DE.ISO-8859-1 ...                               [ ok ]
 *  (5/7) Generating nl_NL.ISO-8859-1 ...                               [ ok ]
 *  (7/7) Generating C.UTF-8 ...                                        [ ok ]
 *  (4/7) Generating en_US.UTF-8 ...                                    [ ok ]
 *  (2/7) Generating de_DE.UTF-8 ...                                    [ ok ]
 *  (6/7) Generating nl_NL.UTF-8 ...                                    [ ok ]
 * Generation complete
 * Adding locales to archive ...                                        [ ok ]
(chroot) Gentoo / # eselect locale list
Available targets for the LANG variable:
  [1]   C
  [2]   C.utf8
  [3]   POSIX
  [4]   de_DE
  [5]   de_DE.iso88591
  [6]   de_DE.utf8
  [7]   en_US
  [8]   en_US.iso88591
  [9]   en_US.utf8
  [10]  nl_NL
  [11]  nl_NL.iso88591
  [12]  nl_NL.utf8
  [13]  C.UTF8 *
  [ ]   (free form)
(chroot) Gentoo / # eselect locale set 2
Setting LANG to C.utf8 ...
Run ". /etc/profile" to update the variable in your shell.
(chroot) Gentoo / # . /etc/profile && export PS1="(chroot) ${PS1}"

Firmware

(chroot) Gentoo / # emerge --ask sys-kernel/linux-firmware

Update /etc/fstab

Determine the UUIDs of /dev/sda*

(chroot) Gentoo / # lsblk /dev/sda  -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID
NAME    SIZE TYPE FSTYPE MOUNT UUID
sdc    46.6G disk
├─sda1  100M part vfat         EFB2-4487
├─sda2    1G part xfs          02a8feb2-328b-4743-8178-c163b8b72aa8
├─sda3    8G part swap         eeff176a-5654-440c-9290-bf9ad12734ba
└─sda4 37.5G part btrfs  /     e7588fd9-ad29-4cf3-b732-6a32a3437b82

Update /etc/fstab with:

  • the UUID of the rootfs for the rootfs whole partition
  • and the same for the root mount point, and the home mount point
  • change the swap file with the swap partition on /dev/sda3

When done /etc/fstab should look something like this:

UUID=EFB2-4487 /boot/efi vfat defaults,uid=0,gid=0,umask=077,shortname=winnt 0 2
UUID=02a8feb2-328b-4743-8178-c163b8b72aa8 /boot xfs defaults 0 0
UUID=e7588fd9-ad29-4cf3-b732-6a32a3437b82 / btrfs noatime,subvol=gentoo 0 0
UUID=e7588fd9-ad29-4cf3-b732-6a32a3437b82 /mnt/rootfs btrfs noatime  0 0
UUID=e7588fd9-ad29-4cf3-b732-6a32a3437b82 /home btrfs noatime,subvol=home 0 0
UUID=eeff176a-5654-440c-9290-bf9ad12734ba none swap sw,pri=10 0 0
tmpfs /dev/shm tmpfs defaults,nodev,nYosuid,noexec 0 0

Make sure to use the right UUIDs.

Set the hostname

(chroot) Gentoo / # echo "gentoo" > /etc/hostname

Install file system tools

(chroot) Gentoo / #emerge -v sys-fs/xfsprogs sys-fs/e2fsprogs sys-fs/dosfstools sys-fs/btrfs-progs sys-fs/lvm2

Install networking tools

(chroot) Gentoo / # emerge -v net-misc/dhcp net-misc/dhcpcd

Install some other tools

(chroot) Gentoo / # emerge -va busybox syslog-ng sys-process/cronie net-misc/chrony app-admin/logrotate app-editors/vim app-admin/sudo

Mount /boot/efi, /home, and /mnt/rootfs

(chroot) Gentoo / # mkdir /mnt/rootfs
(chroot) Gentoo / # mount /boot/efi
(chroot) Gentoo / # mount /home

Configure Grub

The standard parameters for for grub in /etc/default/grub were copied earlier from the original Oracle Linux root volume. These need to be adjusted:

  • update the GRUB_DISTRIBUTOR parameter
  • remove the LVM parameters from the commandline,

The file should look like this:

GRUB_TIMEOUT=5
# GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DISTRIBUTOR="Gentoo"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_TERMINAL="console"
# GRUB_CMDLINE_LINUX="crashkernel=auto LANG=en_US.UTF-8 console=tty0 console=ttyS0,115200 rd.luks=0 rd.md=0 rd.dm=0 rd.lvm.vg=ocivolume rd.lvm.lv=ocivolume/root rd.net.timeout.carrier=5 netroot=iscsi:169.254.0.2:::1:iqn.2015-02.oracle.boot:uefi rd.iscsi.param=node.session.timeo.replacement_timeout=6000 net.ifnames=1 nvme_core.shutdown_timeout=10 ipmi_si.tryacpi=0 ipmi_si.trydmi=0 libiscsi.debug_libiscsi_eh=1 loglevel=4 ip=dhcp,dhcp6 rd.net.timeout.dhcp=10 crash_kexec_post_notifiers"
GRUB_CMDLINE_LINUX="crashkernel=auto LANG=en_US.UTF-8 console=tty0 console=ttyS0,115200 rd.luks=0 rd.md=0 rd.dm=0 rd.net.timeout.carrier=5 netroot=iscsi:169.254.0.2:::1:iqn.2015-02.oracle.boot:uefi rd.iscsi.param=node.session.timeo.replacement_timeout=6000 net.ifnames=1 nvme_core.shutdown_timeout=10 ipmi_si.tryacpi=0 ipmi_si.trydmi=0 libiscsi.debug_libiscsi_eh=1 loglevel=4 ip=dhcp,dhcp6 rd.net.timeout.dhcp=10 crash_kexec_post_notifiers"

Linux kernel

The new Gentoo distribution kernel is linked with a package installkernel. Intstallkernel will install the kernel in /boot, but can also generate an initramfs, and configure grub.

(chroot) Gentoo / # echo "sys-kernel/installkernel dracut grub" >> /etc/portage/package.use/installkernel
(chroot) Gentoo / # emerge -va gentoo-kernel

Update the EFI boot loader

(chroot) Gentoo / # grub-install --efi-directory=/boot/efi
Installing for x86_64-efi platform.
Installation finished. No error reported.

Start the neccessary services

Uncomment the serial console section in /etc/inittab:

# SERIAL CONSOLES
s0:12345:respawn:/sbin/agetty -L 115200 ttyS0 vt100
s1:12345:respawn:/sbin/agetty -L 115200 ttyS1 vt100

And enable the services for sshd, syslog-ng, chronie, crony:

(chroot) Gentoo / # rc-update add sshd default
(chroot) Gentoo / # rc-update add cronie default
(chroot) Gentoo / # rc-update add syslog-ng default
(chroot) Gentoo / # rc-update add chronyd default

Create a user

The OCI default user opc and provide initial passwd:

(chroot) Gentoo / # useradd -g users -G wheel -m -u 2000 -N opc
(chroot) Gentoo / # passwd opc

It is given the uid of 2000, to not interfere with other uids that one may have on other systems.

Set root password

(chroot) Gentoo / # passwd

Update /etc/sudoers

So that anyone in group wheel can sudo:

(chroot) Gentoo / # visudo

And update /etc/sudoers as follows:

## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL:ALL) ALL
%wheel ALL=(ALL:ALL) ALL

Prevent interactive logins over ssh

We only allow login with ssh keys. Update /etc/ssh/sshd_config:

#KbdInteractiveAuthentication yes
KbdInteractiveAuthentication no

Copy opc's ssh's authorized_keys to the new opc user

(chroot) Gentoo / # exit
[root@Gentoo opc]# mkdir /mnt/gentoo//home/opc/.ssh
[root@Gentoo opc]# cp /home/opc/.ssh/authorized_keys /mnt/gentoo//home/opc/.ssh/
[root@Gentoo opc]# chown 2000:users /mnt/gentoo//home/opc/.ssh/
[root@Gentoo opc]# chown 2000:users /mnt/gentoo//home/opc/.ssh/authorized_keys
[root@Gentoo opc]# chmod 700 /mnt/gentoo//home/opc/.ssh/

Reboot

And hope it works...

Refer to the troubleshooting section below in case it does not.

Troubleshooting

OL8 may be booted in case the machine was stopped and started at a later time. This can be fixed by chrooting into the gentoo partition at /dev/sda4, and run another grub-install --efi-directory=/boot/efi. Afterwards reboot.

In case ssh does not work, then it may be possible to use a console connection to enter the Gentoo instance.

In case something else does not work then it may be possible to fix the issue by:

  • stopping the compute instance
  • detaching the boot volume from the compute instance
  • attaching it to another running compute instance
  • chroot into the boot volume and fix the issue.
  • exit the chroot
  • detach the storage
  • attach it to, and boot the compute instance

Pages