Installing Gentoo On An Encrypted Root Partition


There are times when one needs to be able to know that if a computer's hard drive falls into the wrong hands that the information on it cannot be harvested. This is increasingly needed for laptops, desktops, and servers whose hard drives may be storing required-to-be confidential material. Of course, it need not only be such, but, one may wish to have the peace-of-mind that his/her contact information and other personal data is also not accessible (e.g., should their laptop be stolen). The purpose of this post is to detail how configure the Gentoo Linux operating system so that it boots from an encrypted root partition.

DISCLAIMER: Use of this post in any manner is completely and totally at your own risk. You are responsible for what you do with your own equipment/installations. Always read all documentation before using any commands.

Installation Media

In order to install the operating system, one first needs to be able to:

  • boot from a CD/DVD capable of installing Gentoo,
  • be able to partition the hard drive using software on the CD/DVD,
  • be able to run cryptsetup from the CD in order to format the hard drive with encryption,
  • be able to run LVM (Logical Volume Management) software from the CD/DVD, and,
  • be able to format the logical volumes created so the operating system can be installed.

Unlike a normal operating system installation, one cannot reboot the computer and boot into the operating system until enough software is installed so the operating system can actually mount the root partition. Further until such is made to work the only recourse one has is to have reliable boot CDs/DVDs with the required software programs needed to mount partitions so any issues can be fixed.

IMPORTANT: Ensure you have working bootable media on hand before you start. This is especially important if you need to stop and resume things later: make sure you have the necessary bootable media!

The simplest way to ease the burden of an installation is to use the latest Gentoo LiveDVD as it boots a fully working copy of Gentoo Linux with KDE, etc. It also has all of the tools, including cryptsetup, as well as the necessary kernel modules for encryption compiled into the Linux kernel. Without the proper kernel modules, it will not be possible to format the root partition with encryption.

NOTE: The minimal CD for Gentoo is very minimal and nearly everything has to be done manually. Unless you are used to this, I would not recommend using it. The LiveDVD, despite its large size, is much nicer as it configures the network (if it uses DHCP), has firmware for various network cards, can be used with KDE or simply as a text console, has all of the tools needed to encrypt, format, and mount hard drive paritions, etc. This post assumes the use of the LiveDVD. Briefly, the LiveDVD is nice, and convenient whereas the minimal CD is tedious.

Assumptions And Definitions

It is assumed herein:

  • the installation media is the Gentoo Linux LiveDVD (or equivalent),
  • the hard drive is to only have Linux installed on it,
  • there is only one hard drive,
  • Internet access is present, and,
  • a USB memory stick (or equivalent) is on-hand to hold encryption keys needed to boot the system.

You must have a USB memory stick! Do not store any keys on the hard drive.

The following variables are used below to represent a number of things that are system dependent:

Variable Definition
BOOT_DEV Device name of the (unencrypted) boot partition.
ENC_HDD A name given to the cryptsetup-created encrypted device made after calling luksOpen.
INST_HDD Installation hard drive's device name, e.g., /dev/sda. /dev/hdc, etc.
KEY_DEV USB memory stick device name.
KEY_FILE Full path to encryption key.
KEY_MOUNT Mounted directory path for $KEY_DEV.
ROOT_DEV Device name of the (encrypted) root partition.
ROOT_NAME The name of the root logical volume, e.g., root.
SWAP_NAME The name of the swap logical volume, e.g., swap.
VG_NAME The name of the volume group used with LVM, e.g., vg_hostos.

If You Get Stuck…

Since this post is very long, this helpful section is given before the start of any instructions so that it will be noticed and used if needed. If you get stuck after the encrypted partitions have been created and had to shutdown or reboot, then these are the steps to get back up-and-running:

  1. Boot the LiveDVD.
  2. Open a Konsole/Terminal window.
  3. If the network is not already set up, configure it.
  4. Insert and mount your USB key that holds the encryption key.
  5. Mount the encrypted partition so it can be used:
    cryptsetup --key-file $KEY_MOUNT/key.bin luksOpen $ROOT_DEV $ENC_HDD
  6. Activate the volumne group:
    vgchange -a y $VG_NAME
  7. Activate the swap partition:
    swapon /dev/$VG_NAME/$SWAP_NAME
  8. Run:
    mkdir -p /mnt/gentoo
  9. Mount the (encrypted) root partition:
    mount /dev/$VG_NAME/$ROOT_NAME /mnt/gentoo
  10. Run:
    mkdir -p /mnt/gentoo/boot
  11. Mount the (unencrypted) boot partition:
    mount $BOOT_DEV /mnt/gentoo/boot
  12. Copy resolv.conf over from the LiveDVD set up:
    cp -L /etc/resolv.conf /mnt/gentoo/etc/
  13. Mount /proc so it will be accessible from the chroot jail:
    mount -t proc none /mnt/gentoo/proc
  14. Mount /dev so it will be accessible from the chroot jail:
    mount --rbind /dev /mnt/gentoo/dev
  15. Enter a chroot jail on the encrypted drive:
    chroot /mnt/gentoo /bin/bash
  16. Use the environment from the hard drive:
  17. Source /etc/profile:
    source /etc/profile
  18. Fix the prompt to indicate that the chroot jail is active:
    export PS1="(chroot) $PS1"

and then you can perform any required work. Obviously, if you did not create the swap partition or other details, some of the above commands given will not work.

Installation Steps

Partition The Hard Drive

After booting the LiveDVD, use any partition manager to partition the hard drive (e.g., fdisk, gparted, etc.). If you want to partition the drive with GPT then you must install it first:

emerge -av gptfdisk

Create two partitions:

Partition Notes
$BOOT_DEV FDISK type = 83, GPT type = 8300.
Minimum size = 16 MiB. Will remain unencrypted and needs to be large enough to hold contents of /boot.
$ROOT_DEV FDISK type = 7, GPT type = 0700.
Fill rest of hard drive.

Modern hard drives are faster if these partitions are aligned on 2048-byte (or megabyte in gparted) boundaries. This can be set in the expert menu in fdisk and gdisk.

Populate $ROOT_DEV With Random Data

This step is optional but one would likely want to have any previous hard drive content to appear no different than random data. To do this run the following command:

dd if=/dev/urandom of=$ROOT_DEV bs=2048

Create The Encryption Key

In order to encrypt the hard drive one needs to use one or more of:

  • a (long) passphrase, and/or,
  • a random file of binary data which can be encrypted with a passphrase using GPG later.

Ideally, one wants to have a very strong key and would normally choose to create a file with random data. The size of this file depends on the encryption method used. Herein we'll use the AES (i.e., the aes-xts-plain kernel module) with 512 bytes of random data. This key should be generated somewhere other than the installation hard drive (i.e., use the USB memory stick). One can do this with the following steps:

  • Insert and mount the USB memory stick.
  • Change the current directory to the USB memory stick.
  • Create a key file using /dev/random (which requires activity on the computer for entropy):
    head -c 512 /dev/random >keyfile.bin
  • Note that $KEY_FILE is $KEY_MOUNT/keyfile.bin below.

Seriously consider giving the keyfile a meaningful name. I would also suggest incorporating the hard drive's make, model, serial number, and partition number into its name. One can obtain such information without opening the computer by installing and running lshw.

If a passphrase is preferred, then don't specify any --key-file options to cryptsetup below. You can have up to eight (8) key files and/or passphrases set on any partition. If using passphrases, ensure that they are very long so as to have enough entropy. Instead of using passphrases, seriously consider using key files encrypted with GnuPG with a passphrase instead as used in this post.

Create And Mount The Encrypted Partition

Before any disk partition and data can be put onto the encrypted partition, it must first be formated using cryptsetup:

cryptsetup --cipher aes-xts-plain -s 512 \
  --key-file $KEY_FILE luksFormat $ROOT_DEV

NOTE: The Cryptsetup FAQ in response to the question, "Can I resize a dm-crypt or LUKS partition?" notes that aes-xts-plain can only be used for partitions less than 2 TiB. If the encrypted partition is to be greater than or equal to 2 TiB in size then use aes-xts-plain64.

Once the partition has been formatted (with respect to its encryption only), it can then be mounted to provide a device that appears to not be encrypted. Of course, the device is actually encrypted, but, for any programs to make use of it, it needs to have an unencrypted "view". The mount is accomplished using the following command:

cryptsetup --key-file $KEY_FILE luksOpen $ROOT_DEV $ENC_HDD

NOTE: Set $ENC_HDD to something meaningful. For example, if $ROOT_DEV is /dev/sda2 then perhaps set $ENC_HDD to hdd_a2.

The $ENC_HDD representing the unencrypted device is now online. If logical volume management (LVM) is used on it then $ENC_HDD should be thought of as a virtual encrypted hard drive. The full path of the device is: /dev/mapper/$ENC_HDD

Use LVM Create The Partitions To Install The Operating System

Instead of treating $ENC_HDD as a single partition, logical volume management (LVM) will be used to allow (i) the creation of a swap device and (ii) the root partition that the operating system will be installed on. One may not want to have Linux installed into one partition. If so, then instead of creating a single root partition, simply create all of the partitions, appropriately sized, as is appropriate for your circumstances.

Currently, there is only one "physical" (encrypted) volume, /dev/mapper/$ENC_HDD, and the LVM system must be told this (i.e., to create a physical volume):

pvcreate /dev/mapper/$ENC_HDD

With LVM, physical volumes are placed into (various) volume groups within which logical volumes (i.e., "partitions") are created. Since no previous volume groups have been created yet, one needs to be created:

vgcreate $VG_NAME /dev/mapper/$ENC_HDD

In order to do anything with a volume group, it must be activated:

vgchange -a y $VG_NAME

The swap partition should be on $ENC_HDD so it is encrypted. Should anything be swapped out to the hard drive, which will contain data from running programs, it will also be encrypted. Additionally, the swap partition should be contiguously stored, thus, the command used to create the swap partition is slightly different:

lvcreate -L$SWAP_SIZE --contiguous y -n$SWAP_NAME $VG_NAME

NOTE: $SWAP_SIZE will be a value such as 24G (which would be 24 GiB). See the lvcreate man page for further details.

The swap partition's device name is now /dev/$VG_NAME/$SWAP_NAME.

In order to create the root partition in a manner that uses all remaining space available in the volume group, the number of physical extents available needs to be obtained:

  vgdisplay | \
  egrep 'Free[[:space:]]+PE / Size' | \
  awk '{ print $5 }' \

Now the root partition can be created:

lvcreate -l $PESIZE -n$ROOT_NAME $VG_NAME

The root partition's device name is /dev/$VG_NAME/$ROOT_NAME.

Formatting And Mounting Required Partitions

In order to install and use the operating system a chroot jail will be needed and this will require (re-)mounting /dev and /proc in addition to the root and boot partitions so they are accessible from inside the chroot jail:

  1. Format the swap partition:
    mkswap /dev/$VG_NAME/$SWAP_NAME
  2. Turn on the swap partition:
    swapon /dev/$VG_NAME/$SWAP_NAME
  3. Format the root partition:
    mkfs.ext4 /dev/$VG_NAME/$ROOT_NAME
  4. Mount the root partition:
    mkdir -p /mnt/gentoo
    mount /dev/$VG_NAME/$ROOT_NAME /mnt/gentoo
  5. Format the boot partition:
    mkfs.ext4 $BOOT_DEV
  6. Mount the root partition:
    mkdir -p /mnt/gentoo/boot
    mount $BOOT_DEV /mnt/gentoo/boot
  7. Copy resolv.conf over from the LiveDVD set up:
    cp -L /etc/resolv.conf /mnt/gentoo/etc/
  8. Mount /proc so it will be accessible from the chroot jail:
    mount -t proc none /mnt/gentoo/proc
  9. Mount /dev so it will be accessible from the chroot jail:
    mount --rbind /dev /mnt/gentoo/dev
  10. Enter a chroot jail on the encrypted drive:
    chroot /mnt/gentoo /bin/bash
  11. Use the environment from the hard drive:
  12. Source /etc/profile:
    source /etc/profile
  13. Fix the prompt to indicate that the chroot jail is active:
    export PS1="(chroot) $PS1"

Install The Operating System

At this point one should follow the normal installation procedure for Gentoo Linux starting immediately after the steps of formatting and mounting all partitions. Ensure that these packages are also installed:

  • sys-fs/cryptsetup – Must be the same version or higher as what was on the LiveDVD.
  • sys-apps/busybox – If you want a decent shell within initramfs.
  • eix – An available package query tool.
  • sys-kernel/genkernel – Needed to easily build the kernel.
  • sys-kernel/gentoo-sources or sys-kernel/hardened-sources – Linux kernel sources.
  • app-crypt/gnupg – Needed for security (i.e., to have a passphrase on the keyfile).
  • sys-kernel/module-rebuild – Tool to build out-of-kernel kernel modules.
  • app-portage/portage-utils – Additional portage package management tools.
  • sys-apps/util-linux – For /sbin/blkid

Ensuring cryptsetup Version Is Correct

It is possible for the version of cryptsetup on the LiveDVD to be different from the version that is considered "stable" in the operating system. If an older version relative to the LiveDVD of cryptsetup is installed then the system will likely not be able to boot properly. In order to determine if the version of cryptsetup is the same or newer than the one on the LiveDVD, do the following:

  1. Open another console window (i.e., don't use any chrooted terminal session) and run this command as root to obtain the version of cryptsetup on the LiveDVD:
    cryptsetup --version
  2. In the chroot jail console, run:
    emerge cryptsetup
    cryptsetup --version

If the version of cryptsetup in the chroot jail console is older than the one in the LiveDVD console, then Gentoo must be told to use the newer version:

  1. Edit /etc/portage/package.accept_keywords/crypto to contain this line:
    sys-fs/cryptsetup ~amd64
  2. Re-emerge cryptsetup:
    emerge -av --autounmask=y --autounmask-write=y cryptsetup

Configuring And Building The Linux Kernel

After running emerge -av gentoo-sources or emerge -av hardened-sources the linux kernel will have been installed into /usr/src/linux. The steps to configure a Linux kernel are:

  • Run make menuconfig.
  • Set any and all settings.
  • Save and exit the tool.
  • Build the kernel, its modules, and initramfs.
  • Install such to /boot.
  • Ensure the boot loader (e.g., grub) is able to boot the kernel.

While one can roll their own kernel configuration, this post focuses on using genkernel with the gentoo-sources or hardened-sources packages for these reasons:

  • the genkernel utility completely automates everything, except this post will intentionally run make menuconfig manually,
  • booting using an encrypted root partitions as described in this post will require the following to be built and installed in initramfs:
    • statically compiling sys-fs/cryptsetup,
    • statically compiling app-crypt/gnupg,
    • statically compiling (optionally) sys-apps/busybox,
    • statically compiling in disklabel (UUID) support, and,
    • writing a script/program to prompt the user for a key-file or passphrase in order to be able to mount the encrypted system.

In short, using genkernel automates a number a lot of extra work that most won't need to be concerned with on practical level, especially if time-constrained. In order to have genkernel automate the kernel building process, do the following:

  1. Change the current working directory to /usr/src/linux:
    cd /usr/src/linux
  2. Copy the LiveDVD's kernel configuration to the current directory:
    zcat /proc/config.gz >.config
  3. Configure the kernel by running make menuconfig and ensure the following options are set to Yes to avoid issues when booting:
    • Cryptographic API –> CBC support
    • Cryptographic API –> ECB support
    • Cryptographic API –> XTS support
    • Cryptographic API –> HMAC support
    • Cryptographic API –> all CRC32c options
    • Cryptographic API –> MD5 digest algorithm
    • Cryptographic API –> Michael MIC keyed digest algorithm
    • Cryptographic API –> SHA1 digest algorithm
    • Cryptographic API –> SHA224 and SHA256 digest algorithm
    • Cryptographic API –> SHA384 and SHA512 digest algorithms
    • Cryptographic API –> all AES options
  4. Before running genkernel, ensure these settings are set in /etc/genkernel.conf:
  5. If you use MAKEOPTS in /etc/make.conf, then ensure you set the same in genkernel as genkernel does not use /etc/make.conf at all. (See this post on how to set MAKEOPTS.)
  6. Build the kernel, its modules, necessary statically linked software, and install it to /boot:
    genkernel all
  7. Determine any external-to-the-kernel modules for your system:
    module-rebuild populate
  8. Rebuild any external-to-the-kernel modules:
    module-rebuild rebuild

Configuring /etc/fstab and grub

Determining All Partitions' UUIDs

Run blkid and note the UUIDs for the following partitions:

  • $BOOT_DEV – This is the unencrypted boot partition.
  • $ROOT_DEV – This is the encrypted root partition UUID which grub will need in order to find the partition at boot time.
  • /dev/mapper/$VG_NAME/$SWAP_NAME – This is the swap partition.
  • /dev/mapper/$VG_NAME/$ROOT_NAME – This is the root partition that the booted operating system uses.

NOTE: The output from blkid has quotation marks surrounding them. You'll need to remove the quotation marks when placing the UUIDs in /etc/fstab and in grub.conf.

Configuring /etc/fstab

Edit /etc/fstab so that it contains the following:

UUID=ROOT_NAME_UUID   /            ext4    errors=remount-ro     0 1
UUID=BOOT_DEV_UUID    /boot        ext4    noauto,noatime        0 1
UUID=SWAP_NAME_UUID   none         swap    sw                    0 0
/dev/cdrom            /mnt/cdrom   auto    noauto,user,ro        0 0
proc                  /proc        proc    defaults              0 0
shm                   /dev/shm     tmpfs   nodev,nosuid,noexec   0 0


  • ROOT_NAME_UUID is the UUID value for /dev/$VG_NAME/$ROOT_NAME,
  • BOOT_DEV_UUID is the UUID value for $BOOT_DEV, and,
  • SWAP_NAME_UUID is the UUID value for /dev/$VG_NAME/$SWAP_NAME.

Protecting The Keyfile

When the key was generated earlier, it was generated as a binary file. One, however, does not want to walk around with a key that that has no passphrase in case it is lost or stolen, one will need to crack the passphrase in order to obtain the key. To convert the key to a GPG protected key, do the following:

  1. Mount the USB memory stick with the key.
  2. Run:
    gpg --symmetric -o $KEY_FILE.gpg $KEY_FILE

Configuring grub

Except for editing /boot/grub/grub.conf installing and configuring grub is straight-forward:

  • If grub has not been installed yet, do so:
    emerge -av grub
  • Using the UUID for $ROOT_DEV from the previous section, edit /boot/grub/grub.conf (see below).
  • Copy the active mounts:
    cat /proc/mounts >/etc/mtab
  • Install grub to the hard drive's boot sector:
    grub-install --no-floppy $INST_HDD

Examine $ROOT_DEV and note the drive letter and partition number which are the last two characters in its name. The grub boot loader uses numbers to identify drives and partitions starting from 0, therefore, drive letters 'a', 'b', 'c', etc. correspond to 'hd0', 'hd1', 'hd2', etc. and partition numbers '1', '2', '3', etc. correspond to '0', '1', '2' etc. This matters since the line with root (hd0,1) needs to be set to the correct drive and partition number as per the system being installed. Further, the appropriate file names, UUID, $VG_NAME, $KEY_DEV, $KEY_FILE, $KEY_MOUNT, $ROOT_NAME must be set/replaced with the proper values for grub to boot. Knowing this, entries in /boot/grub/grub.conf will be similar to:

title Gentoo Linux (Keyfile Boot)
root (hd0,0)
kernel /boot/kernel-genkernel-x86_64-2.6.39-gentoo-r3 root=/dev/ram0 crypt_root=UUID=ROOT_DEV_UUID real_root=/dev/mapper/$VG_NAME-$ROOT_NAME root_keydev=$KEY_DEV root_key=$KEY_FILE.gpg rootfstype=ext4 key_timeout=0 dolvm
initrd /boot/initramfs-genkernel-x86_64-2.6.39-gentoo-r3

title Gentoo Linux (Passphrase Boot)
root (hd0,0)
kernel /boot/kernel-genkernel-x86_64-2.6.39-gentoo-r3 root=/dev/ram0 crypt_root=UUID=ROOT_DEV_UUID real_root=/dev/mapper/$VG_NAME-$ROOT_NAME rootfstype=ext4 key_timeout=0 dolvm
initrd /boot/initramfs-genkernel-x86_64-2.6.39-gentoo-r3


Finally, the system can be rebooted. If everything was set correctly, the system should fully reboot. If not, follow the instructions in the "If You Get Stuck…" section to be able to access the contents of the encrypted partition so any issues can be fixed.

Kindly contact me should any typos or errors be found within this post.

Parallel Builds With Gentoo's Emerge


Gentoo allows one to specify the degree of concurrency to be employed when emerging packages with Portage in two ways by specifying:

  • the -j and the -l options in the MAKEOPTS variable in /etc/make.conf, or,
  • the --jobs and --load-average options on the emerge command line or in the EMERGE_DEFAULT_OPTS variable in /etc/make.conf.

The article describes some of my experiences with using the above parameters.

Determining Hardware Limits On Parallelism

Assuming the operating system being used to run Portage is Linux, one needs to determine the number of CPU cores and theads available for parallelism. This can be determined by executing the following:

grep '^processor' /proc/cpuinfo | sort -u | wc -l

For brevity, this amount will be referred to as NJOBS below, i.e., as if this were run:

NJOBS=$(grep '^processor' /proc/cpuinfo | sort -u | wc -l)

Maximizing Processor Saturation

Ideally one would want all processors busy performing work as this would allow one to minimize the total amount of time compiling code. However, one does not want the system load to become excessive for the following reasons:

  • to minimize process switching, and,
  • to keep the system responsive to user input.

The first step in this process is to set MAKEOPTS to have as its maximum number if parallel tasks to be NJOBS+1 and to limit starting any new jobs if the load is NJOBS or higher in /etc/make.conf:

MAKEOPTS="-j$((NJOBS+1)) -l${NJOBS}"

where the -j option sets the maximum number of parallel jobs that can be run via make and the -l prevents any new parallel job starting unless the load is below the amount specified. (The reason the number of jobs is set to one higher than the number of processors is to help ensure saturation of processor utilization.)

There is no need to set an NJOBS variable in /etc/make.conf as hardware will not change, so one should simply substitute the proper values in MAKEOPTS. For example, MAKEOPTS suitable for an i7 processor would be:

MAKEOPTS="-j9 -l8"

Setting MAKEOPTS is very safe as there are very few packages with parallel make issues. Typically, if there are issues, the ebuild for that package will turn off the option, or, will give notice that -j1 must be used.

Setting MAKEOPTS will improve the build times of a number of packages, however:

  • many packages don't perform parallel makes, and,
  • many packages' build procedures won't saturate all processors with load.

This is most apparent when running long-build tasks such as emerge -eav world or when building large software programs such as Firefox, Chromium, or LibreOffice. In my experience an i7 processor will have a load between 1.00 and 2.00 most of the time if only MAKEOPTS is set. This is not even close to ideal.

To better utilize processors, one has to tell emerge to also run parallel jobs. This is done using the --jobs and --load-average options with emerge:

emerge --jobs=${NJOBS} --load-average=${NJOBS} world

Here, unlike MAKEOPTS, one need only set the jobs and the load limit to the number of processors as tasks will be run within such that will generate load. Since there is a load average limit specified here and in MAKEOPTS the system should not become overly busy and start thrashing or need to excessive amounts of process switching. (If such is an issue, then lower the load average settings.)

Since emerge's command line overrides anything set in /etc/make.conf, I set EMERGE_DEFAULT_OPTS in /etc/make.conf as follows:

EMERGE_DEFAULT_OPTS="--jobs=${NJOBS} --load-average=${NJOBS}"

i.e., for an i7 this would be:

EMERGE_DEFAULT_OPTS="--jobs=8 --load-average=8"

so I don't have to specify such on the command line. For packages that have issues being compiled in parallel, one need only override --jobs on the command line setting it to 1:

emerge -j1 world

Dealing With Failed Builds

There are some instances of packages that will simply not build when emerged as parallel jobs. This poses a significant issue if one was performing an emerge world of hundreds or thousands of packages. Fortunately, emerge has the ability to resume a compile as well as to skip the first package when resuming. Assuming the packages are already built on the computer, you can safely skip the package and rebuild it later with -j1. If you are extra careful not to do such more than once (or you'll lose the ability to resume), you can even do this to build the package (e.g., in another window) and when done, emerge -rav --skipfirst to resume the build process.

Want More Output?

When the number of jobs is greater than one, there is only a summary output. To see the tasks actually being performed, run:

qlop -c

or the continuously updating:

while true ; do clear ; qlop -c ; sleep 2 ; done

To see the actual build output that one sees with emerge -j1, simply run tail for the package, PKG, being built:

tail -f /var/tmp/portage/*/${PKG}*/temp/build.log

by replacing ${PKG} with the name of the package.

Different Values For Jobs and Load Averages

Elsewhere on the Internet, I've seen people use different values such as having the number of processors and assigning half to MAKEOPTS and the other half to emerge. Unfortunately, this will on average saturate and utilize only half of the processors. In my experience, even this "average" does not happen frequently!

Logically, it is much better to set the jobs to the number of processors and then to use load average settings to limit the load to limit the total number of parallel tasks created during the build process. This strategy, as described above, allows all processors to be used without excessive loads being created (e.g., on an i7 the highest loads I've seen with the above settings is approximately 9.0). It also allows parallelism to occur when packages are being built that don't use parallel make (or are limited in how much parallelism they can do). This is why the emerge load average value is set as it is above –as the MAKEOPTS load average ensures parallel tasks only start running if the load is not too high. My experience with such are very positive with good to excellent load averages when things can be done in parallel.


In my experience, using the settings outlined above significantly speeds up compiles on multi-core machines. There are only a couple of packages that don't like the parallel emerge where I need to intervene but the rest build without a problem and my cores/processors become mostly utilized instead of being mostly idle.

Linux Containers, /dev/pts/ptmx, and Gentoo

For virtualization technologies (e.g., environments, machines) Linux now supports containers which allow multiple instances of the devpts filesystem. This allows the /dev/pts instance indices in one virtual environment to be independent of the indices allocated in another environment.

As detailed in the kernel file Documentation/filesystems/devpts.txt, this requires the kernel option:


and the "-o newinstance" mount option when mounting devpts.

Gentoo's sys-apps/openrc-0.8.3-r1 configuration has a /dev/init.d/devfs script in the sysinit runlevel. Despite it name and the fact that the system uses udev, the devfs initscript states that it mounts "required stuff as user may not have [them] in /etc/fstab". Unfortunately, the devfs script does not check for entries in fstab before mounting the devpts and shm filesystems. Fortunately, the Documentation/filesystem/devpts.txt nicely mentions what to do if initscripts are not updated to handle CONFIG_DEVPTS_MULTIPLE_INSTANCES. Since one doesn't likely want to do such things manually after every reboot and it is generally a bad idea to start editing a distribution's installation scripts, here's an initscript that performs the devpts.txt file's instructions:


description="Multiple PTY fix for /dev/ptmx"

  after udev devfs

  if [ -e /dev/pts/ptmx ]; then
    # Use next line if devpts is in /etc/fstab...
    mount -o remount /dev/pts
    # Or uncomment next line...
    #chmod 0666 /dev/pts/ptmx
    rm /dev/ptmx
    ln -s pts/ptmx /dev/ptmx
    return 0
    echo "/dev/ptmx does not exist!"
    return 1

which also requires this line to be in /etc/fstab (but adjust the perms to your liking):

devpts /dev/pts devpts rw,relatime,gid=5,mode=666,ptmxmode=666 0 0

and to run in the sysinit runlevel:

# rc-update add ptmx-fix sysinit

Test it by rebooting and checking that /dev/ptmx is a symlink to /dev/pts/ptmx and the permissions of /dev/pts/ptmx are 0666. 🙂