Sakaki's EFI Install Guide/Preparing the LUKS-LVM Filesystem and Boot USB Key

From Gentoo Wiki
Jump to: navigation, search

In this section, we'll be shadowing Chapter 4 of the Gentoo handbook (and, although we're going to start to diverge considerably, you may want to read that chapter before proceeding, as it has some useful background information).

The process we'll be following here is:

  1. First, we'll format the smaller USB key (discussed earlier) so that it can support booting under UEFI (although there'll be no bootable kernel on it, yet). We'll then mount it.
  2. Next, we'll create a pseudo-random binary blob of key data that will be used to secure the main computer drive, encrypt this with a passphrase using GPG, and store the result on the USB key.
  3. Then, we will create a new GPT (GUID partition table) partition on the target machine's main drive, using the space we freed up from Windows earlier in the tutorial.
  4. We'll then (optionally) overwrite that partition with pseudo-random data.
  5. Next, we'll format the partition using LUKS (secured with the key data created in step 2).
  6. We'll then (optionally) add a fallback passphrase to the LUKS container.
  7. Then, we'll create an LVM physical volume (PV) on the LUKS partition, create an LVM volume group (VG) with just that one physical volume in it, and then create three logical volumes (LVs) (for the Gentoo root, swap and home partitions) utilizing that physical volume.
  8. Finally, we'll format the logical volumes appropriately, and mount them so that they can be used in the rest of the installation.

Let's go!

Formatting and Mounting the UEFI-Bootable USB Key

We are going to use our smaller (>= 128 MB) USB key as the boot device for Gentoo Linux. Since we want it to work under UEFI, we must format it using GPT with a single fat32 EFI system partition.

This process will wipe everything on the USB key, so be sure to back it up if necessary.

Issue (using of course the ssh / screen terminal we have just established):

livecd ~ #lsblk

And note the output. Then, insert the smaller capacity USB key into one of the remaining free USB slots on the target machine, and determine its device path. We will refer to its path in these instructions as /dev/sdY, but in reality on your system it will be something like /dev/sdc, /dev/sdd etc. You can find what it is, by issuing lsblk again, and noting what has changed:

livecd ~ #lsblk

(note that the initial /dev/ prefix is not shown in the lsblk output)

The minimal-install image shouldn't auto-mount the USB key, even if it has any existing partitions, but double-check to make sure (no mountpoints for the device should be shown in the output of the above command).

Now, using parted, we will create a single primary partition, sized so as to fill the USB key completely (you can of course use a more modest extent if your drive is much larger than the minimum required size), and set its somewhat confusingly named 'boot' flag (i.e., mark the partition as a GPT system partition). Issue:

livecd ~ #parted -a optimal /dev/sdY
GNU Parted 3.2
... additional output suppressed ...
(parted) mklabel gpt
Warning: The existing disk label on /dev/sdY will be destroyed and all data on
this disk will be lost. Do you want to continue?
Yes/No? yes
(parted) mkpart primary fat32 0% 100%
(parted) set 1 BOOT on
(parted) quit
Replace /dev/sdY in the above command with the path of the USB key you found above, such as /dev/sdc or /dev/sdd etc.

Next, we need to format the partition fat32:

livecd ~ #mkfs.vfat -F32 /dev/sdY1
Replace /dev/sdY1 in the above command with the path of first partition on the USB key, such as /dev/sdc1 or /dev/sdd1 etc.
On some machines, a new drive letter will be assigned to the USB key after it has been edited by parted in this fashion. For example, if the drive was /dev/sdc prior to editing, it may become /dev/sdd afterwards. For avoidance of doubt, this issue will not affect most users; but, it is simple to check, by using lsblk.

Now we create a temporary mountpoint and mount the partition:

livecd ~ #mkdir -v /tmp/efiboot
livecd ~ #mount -v -t vfat /dev/sdY1 /tmp/efiboot
As before, remember to subsitute for /dev/sdY1 in the above.

Creating a Password-Protected Keyfile for LUKS

We will next create a (pseudo) random keyfile (for use with LUKS). This keyfile will be encrypted with GPG (using a typed-in passphrase) and then stored on the USB key.

The point of this is to establish dual-factor security - both the (encrypted) keyfile, and your passphrase (to decrypt it) will be required to access the LUKS data stored on the target machine's hard drive. This means that even if a keylogger is present, should the machine be stolen - powered down but without the USB key - the LUKS data will still be safe (as the thief will not have your encrypted keyfile). Similarly, (assuming no keylogger!) if your machine were to be stolen powered down but with the USB key still in it, it will also not be possible to access your LUKS data (as in this case the thief will not know your passphrase).

Note that we are going to create a (one byte short of) 8192KiB underlying (i.e., binary plaintext) keyfile, even though, for the symmetric LUKS cipher we'll be using (Serpent), the maximum supported key size is 256 bits (32 bytes) (or two 256 bit keys = 512 bits = 64 bytes in XTS mode, as explained later). This works because LUKS / cryptsetup uses the PBKDF2 key derivation function to map the keyfile into the actual (user) key material internally (which in turn is used to unlock the master key actually used for sector encryption / decryption), so we are free, within limits, to choose whatever size keyfile we want. As such, we elect to use the largest legal size, so as to make it (very slightly) harder for any data capture malware (in low-level drivers, for example) to intercept the file and squirrel it away, or transmit it over the network surreptitiously. In theory, the cryptsetup system can support keyfiles up to and including 8192KiB (execute cryptsetup --help to verify this); in practice, due to a off-by-one bug, it supports only keyfiles strictly less than 8MiB. We therefore create a keyfile of length (1024 * 8192) - 1 = 8388607 bytes.

Note that we'll use the /dev/urandom source to create the underlying (binary plaintext) pseudo-random keyfile, and then pipe it to gpg to encrypt (using a passphrase of your choosing). The resulting binary ciphertext is saved to the USB key. This avoids ever having the binary plaintext keyfile stored on disk anywhere (and indeed not even you need ever see the unencrypted contents). Enter:

livecd ~ #export GPG_TTY=$(tty)
livecd ~ #dd if=/dev/urandom bs=8388607 count=1 | gpg --symmetric --cipher-algo AES256 --output /tmp/efiboot/luks-key.gpg
Enter passphrase
Passphrase <your new passphrase>
Please re-enter this passhprase
Passphrase <your new passphrase again>
... further output suppressed ...
We need to set the GPG_TTY variable here, otherwise gpg's pinentry password system may misbehave. If you are connecting over ssh, and your helper system has locale settings not available within the minimal install environment, you may get complaints about 'no LC_CTYPE known' printed by pinentry; these can generally be ignored, and result from sshd on the target machine attempting to use the helper machine's environment.[1]
We are using the symmetric AES cipher here with a 256 bit key (derived from your passphrase) to protect the keyfile. We'll use a different cipher (Serpent) in LUKS to protect the hard drive partition. Note also that the /tmp/efiboot/luks_key.gpg file will be larger than 8388607 bytes, due to the GPG 'wrapper'.
If you lose the (encrypted) keyfile, or forget the passphrase, it's game over for your LUKS data. Therefore, be sure to backup both keyfile and passphrase (to separate, secure locations).

What passphrase you choose to protect your LUKS keyfile is, of course, entirely up to you, but do consider the approach of using a longer list of everyday words, rather than the more traditional cryptic str1ng5 @f characters. Advantages include:[2]

  • it's easier to hit a reasonable level of entropy;
  • you are less likely to forget the resulting passphrase; and
  • your passphrase will be more robust in the face of keymapping snafus at boot time.

Creating a New GPT Partition on the PC's Main Drive

Our next task is to create a new GPT partition on the target PC's hard drive (which we freed up space for earlier).

We will use the parted tool, instruct it to use sectors for units, and then display the free space on the current drive. We'll then create a new primary partition on that drive using all the available space indicated.

Please take particular care with this step. parted can cause catastrophic data loss if misused and, unlike fdisk, writes changes immediately.

We must first find the device path of the main hard drive on the target machine. We will refer to this as /dev/sdZ in the following text, but it will be something like /dev/sda, /dev/sdb etc. on your machine. Check the actual path with:

livecd ~ #lsblk

If you are dual booting with Windows, you'll probably see that the desired drive has between four and six existing partitions, depending on your version of Windows (note that the initial /dev/ prefix is not shown in the lsblk output). None of these should be mounted (all should have blank mountpoints in the output of lsblk).

Now we will create the partition:

livecd ~ #parted -a optimal /dev/sdZ
GNU Parted 3.1
... additional output suppressed ...
(parted) unit s
(parted) print free
... additional output suppressed ...
Number  Start      End         Size        File system  Name                          Flags
... additional output suppressed ...
        AAAs       BBBs        CCCs        Free Space

(parted) mkpart primary AAAs BBBs
(parted) quit
Replace /dev/sdZ in the above command with the path of the target machine's main drive (the one on which Windows is installed), such as /dev/sda. Note also that we need to target the device itself, and not a partition within it, so for /dev/sdZ in the above command, use e.g. /dev/sda and not /dev/sda1; /dev/sdb and not /dev/sdb1, etc.
You should of course also substitute for AAA and BBB, whatever output is displayed for the boundaries of the free space when you issue the print free. For example, if you got back
        89362432s  500118158s  410755727s  Free Space
you would issue
(parted) mkpart primary 89362432s 500118158s
You can make the partition smaller, if you do not wish to use all of the remaining space for the Gentoo install. It can be useful to reserve some space (<=1GiB, say) for e.g. an emergency recovery partition, but whether to do so is entirely up to you.
You may see multiple blocks of free space listed (particularly with modern versions of Windows 10; in this case, just use the largest one.
The suffix 's' in the dimensions passed above tells parted that you are using 'sector' units. Do not omit it!
If parted complains that your new partition is not properly aligned for best performance, you may wish to cancel the mkpart, then try again with modified values: rounding the start address up to the nearest 2048, and the end address down to the nearest 2048 sectors. For example, if the largest free block prior to creation of the new partition was reported as
224107278s  469868543s  245761266s  Free Space
you could do the following on your helper PC to calculate optimal values:
user@pc2 $echo "$((((224107278 + 2047) / 2048) * 2048))s $((469868543 - (469868543 % 2048)))s"
224108544s 469866496s
so you would issue:
(parted) mkpart primary 224108544s 469866496s
Obviously, adapt using the sector start and end addresses for the free space block on your drive! Incidentally, the 'magic number' 2048 is a safe choice for most drives; but you can easily calculate the actual optimal value for your own device, if desired.[3]
If the drive you are using has not yet been partitioned, the print free command will not output data as above. In such a case, you will need to issue a mklabel gpt command within parted first. However, do not do this (i.e., issue mklabel gpt) on an already-partitioned drive; you will lose all the data on there if you do!
Users who are targeting a fresh disk in this way may also find it easier to create the partition itself with the parted command mkpart primary 0% 100%, as this will deal with all sector alignment issues etc. (Users with existing data on their drives should not do this however, but instead follow the commands given in the main text.)
Additionally, users who are not co-installing with Windows may find it useful to create two partitions on /dev/sdZ: the main one as specified above, and a second EFI system partition. This will allow e.g. subsequent migration of the kernel from the boot USB key to the main drive later if desired. Users who do intend to dual-boot with Windows should ignore this point: your hard drive already contains an EFI system partition.

Now check that the sector has been created correctly. We'll issue an lsblk command again:

livecd ~ #lsblk

Take note of the new sector device path (note that the initial /dev/ prefix is not shown in the lsblk output). We will refer to this as /dev/sdZn in the below, but it will actually be something like /dev/sda7, /dev/sdb7 etc. If you have a non-standard Windows setup, the number of the new partition may also be something other than 7 (for example, on older Windows 10 and most Windows 8 systems it is more likely to be 5), so do please double check.

Overwriting the New Partition with Pseudo-Random Data (Optional Step)

You can skip this step if you like. The main reasons to perform an overwrite are:

  • to purge any old, unencrypted data that may still be present in the partition (from prior use); and
  • to make it somewhat harder for an attacker to determine how much data is on your drive if the machine is compromised.

However, it may make things slower on a solid-state drive, by forcing any new writes to first delete a sector (once any overcapacity has been exceeded), rather than simply writing to a fresh, unused one (and furthermore, it cannot completely be guaranteed that old data has been wiped, when using such devices).

This command may take a number of hours to complete.

The step below will destroy existing data on the partition; please double check to ensure you have the correct device path (e.g., /dev/sda7 etc.) before continuing.
livecd ~ #dd if=/dev/urandom of=/dev/sdZn bs=1M status=progress && sync
Replace /dev/sdZn in the above command with the device path for the partition we just created, e.g., /dev/sda7.

You will be able to see dd slowly progressing. Wait for it to complete before proceeding to the next step.

Formatting the New Partition with LUKS

The next step is to format the partition using LUKS. LUKS, which stands for Linux Unified Key Setup, is as the name suggests primarily a way to manage the encryption keys for whole-partition (or drive) encryption. It does this by first generating a high-entropy, secret, master key, which is then encrypted using between one and eight user keys (themselves first pre-processed by PBKDF2).

The target partition itself begins with a LUKS metadata header, followed by the encrypted master key material corresponding to each of the 8 possible user 'slots', and finally the bulk, encrypted (payload) data itself (the encrypted sector data for the partition).

The LUKS master key itself is never stored in unencrypted form on the partition, nor (unless you explicitly request it) even made visible to you, the user.

LUKS uses a cryptographic splitting and chaining technique to artificially inflate the size of the key material for each slot into a number of interdependent 'stripes'. This is done to increase the likelihood that, when a slot is modified (a user key is revoked, or changed, for example), that the old key material is, indeed, irrecoverable (necessary, since under LUKS the partition master key is never changed once created). Be warned though, that with solid-state drives no guarantees can be given, if you change a user key, that the old key material is not retained on the drive somewhere (due to wear-levelling etc.).[4]

LUKS functions are accessed via the cryptsetup program, and use dm-crypt for the back-end processing. Note that LUKS is agnostic as to the actual symmetric encryption method used, provided it is supported by dm-crypt. You can get a list of the (currently loaded) encryption and hash algorithms by issuing:

livecd ~ #cat /proc/crypto

(You may have others available as kernel modules, which will be loaded when required).

What we need to do is tell cryptsetup:

  • the underlying block cipher we want to use (block ciphers work on fixed-size units, or blocks, of data to encrypt or decrypt at a time),
  • the key length to use with this cipher,
  • the way we'll tweak it to en/decrypt amounts of data larger than one cipher block (many ciphers use a 16-byte block, and sectors, the indexing unit, are larger than this),
  • what processing, if any, should be applied to the sector index number during IV computation, and
  • the hash algorithm used for key derivation (under the PBKDF2 algorithm within LUKS)

This isn't a cryptography primer (see this article for further reading), but here's a thumbnail justification for the choices made:

  • we will use Serpent as the block cipher; this came second in the AES competition mainly for reasons of speed, but has a more conservative design (32 rounds as opposed to 14) and scored a higher safety factor when compared to the Rijndael algorithm that won the competition (and which, accordingly, is now commonly referred to as 'AES');
  • for security, we'll use the longest supported key length for Serpent, which is 256 bits (see the following point, however);
  • we will use XTS mode to both extend the cipher over multiple blocks within a sector, and perform the by-sector-index 'tweaking'; this approach overcomes the security weakness in the more conventional CBC / ESSIV methodology, whereby an attacker, although unable to read the encrypted material, can yet, if they know the cleartext for that sector (possible for some system files), arbitrarily modify alternating blocks to inject shellcode[5]; this is a non-trivial concern for a dual-boot machine where the Windows side of things is untrusted (and has access to the encrypted contents of the LUKS partition when running). Note that since XTS mode actually requires two keys, we must pass an effective key length of 512 (= 2 x 256) bits to cryptsetup;
  • as XTS is a (modified) counter mode, we will simply pass the untransformed ("plain") 64-bit sector index to it (using a 64-bit index will allow for disks > 2TiB);[6]
  • we will use Whirlpool as the user key hashing function for LUKS' PBKDF2 processing; it is a 512 bit hash that has been recommended by the NESSIE project. Note that Whirlpool hash will appear in the output from /proc/crypto as wp512 (if loaded).

We decrypt our keyfile from the USB key (using gpg) and pipe it to cryptsetup, to avoid the unencrypted keyfile having to be saved to disk. The --cipher and --hash strings instruct cryptsetup to use the settings just discussed.

The step below will destroy existing data on the partition; please double check to ensure you have the correct device path (e.g., /dev/sda7 etc.) before continuing. When you pipe the keyfile in this way, cryptsetup will not ask you if you are sure prior to formatting.
livecd ~ #gpg --decrypt /tmp/efiboot/luks-key.gpg | cryptsetup --cipher serpent-xts-plain64 --key-size 512 --hash whirlpool --key-file - luksFormat /dev/sdZn
<when prompted, type the passphrase for the gpg keyfile you setup earlier>
... additional output suppressed ...
Replace /dev/sdZn in the above command with the device path for the partition we just created, e.g., /dev/sda7.
Also, you may see some errors of the form device-mapper: remove ioctl on XXX failed: Device or resource busy; these can generally be ignored, provided the luksDump command (described below) works.
Depending on how soon after first creating the gpg keyfile you issue the above command, you may find that you are not prompted for a passphrase at all. That's because your passphrase has been (temporarily) cached behind the scenes, for convenience, by gpg-agent. If you want to force the passphrase prompt (for example to double-check you have the passphrase written down correctly!), you can do so by issuing the following prior to the luksFormat command above:
livecd ~ #echo RELOADAGENT | gpg-connect-agent
By default, cryptsetup uses /dev/random as its random number generator (RNG); this may run out of entropy when formatting the partition and print a warning; if this happens, just run your finger over the touchpad of the target machine (or move its mouse, if attached) until the process completes.
If you use the Whirlpool hash (as we have done), be aware that you will not be able to open the LUKS container using dev-libs/libgcrypt < v1.6.0, because of a bug in those earlier versions when writing data to the Whirlpool hash function in chunks.[7]
If you'd rather use a vanilla approach, omit the --cipher and --hash arguments; cryptsetup will then revert to its compiled-in defaults (which you can see using)
livecd ~ #cryptsetup --help
At the time of writing, this implies aes-xts-plain64, so Rijndael (AES) rather than Serpent, with a 256bit key (which really means 2 x 128bit keys, given XTS mode, so less secure than our 512bit (= 2 x 256bit) variant), and SHA1 for the LUKS password hashing, which again is arguably less good than Whirlpool. Ultimately, the choice is yours of course.
Although you can specify an additional hash postfix in the --cipher string (e.g. serpent-xts-plain64:whirlpool rather than simply serpent-xts-plain64), it will be ignored by the kernel in plain64 mode.[8] As such, you should omit it (as we have done). Remember, this postfix is only used to specify the hash function for IV processing (if any), and so is relevant in ESSIV mode, for example. It has nothing to do with the hash used in the LUKS header, which is specified by the --hash argument, as above.

Check that the formatting worked, with:

livecd ~ #cryptsetup luksDump /dev/sdZn
Replace /dev/sdZn in the above command with the device path for the LUKS partition, e.g., /dev/sda7.

This should print out information about the LUKS setup on the sector, and show that one of the 8 keyslots (slot 0) is now in use (incidentally, pointing out that LUKS does not provide any plausible deniability about the use of encryption! You can detach the header and store it on a separate device, but we won't do that here as it isn't supported in the standard genkernel init scripts that we'll rely on later.).

If the LUKS header gets damaged, your encrypted data will be lost forever, even if you have a backup of the GPG key and passphrase. Therefore, you may wish to consider backing up this header to a separate device, and storing it securely. See the LUKS FAQ for more details on how to do this.
For example, to save a copy of the current LUKS header to your boot USB key (doing so is optional), you could now issue, per the FAQ:
livecd ~ #cryptsetup luksHeaderBackup /dev/sdZn --header-backup-file /tmp/efiboot/luks-header.img

Replace /dev/sdZn in the above command with the device path for the LUKS partition, e.g., /dev/sda7.
Be aware that if you do keep a LUKS header backup in this fashion, and subsequently revoke any of the keyslots, that the old keys will still be usable to unlock the LUKS partition, to those with access to that header backup file.

Adding a Fallback Passphrase (Optional Step)

Since LUKS supports up to 8 user key 'slots', you can, if you wish, add an additional (traditional) passphrase to your LUKS container now. This is not intended for use day-to-day, but simply as a last-resort fallback, should you lose the USB key with the GPG keyfile on it, for example.

If you are concerned that your machine might already contain a keylogger, do not perform this step; click here to jump to the next task instead.
If, at the conclusion of the tutorial, you wish to be able to switch to booting without using the GPG keyfile, then you should setup a fallback passphrase now.

Unfortunately, the necessary cryptsetup command requires that we provide an existing valid user key in addition to the new one we want to add. If we pipe this in directly from gpg (as we did earlier), then cryptsetup will not prompt correctly for a new passphrase. To get around this issue, without writing the existing GPG key out in binary plaintext form to a disk file, we'll use a named pipe.

Assuming you're using screen, hit Ctrla followed by c to start a new virtual console. Then type:

livecd ~ #mkfifo /tmp/gpgpipe
livecd ~ #echo RELOADAGENT | gpg-connect-agent
livecd ~ #gpg --decrypt /tmp/efiboot/luks-key.gpg | cat - >/tmp/gpgpipe
<when prompted, type the passphrase for the gpg keyfile you setup earlier>
... additional output suppressed ...

(The slightly odd approach of piping via cat is intentional.) This will block once you type in your passphrase, as nothing is connected to the other end our the named pipe (yet). Now switch back to the original virtual console with Ctrla followed by p, and enter:

livecd ~ #cryptsetup --key-file /tmp/gpgpipe luksAddKey /dev/sdZn
Enter new passphrase for key slot: <type your new fallback passphrase>
Verify passphrase: <type your fallback passphrase again>
Replace /dev/sdZn in the above command with the device path for the LUKS partition, e.g., /dev/sda7.

Verify that this worked by issuing:

livecd ~ #cryptsetup luksDump /dev/sdZn
Replace /dev/sdZn in the above command with the device path for the LUKS partition, e.g., /dev/sda7.

You should now see slot 1 is enabled, as well as slot 0. Now, remove the named pipe, since we no longer need it:

livecd ~ #rm -vf /tmp/gpgpipe

Lastly, switch back to the second virtual console with Ctrla followed by n, and then hit Ctrld to close it out and return to the original console again.

Creating the LVM Structure (PV->VG<-LVs) on Top of LUKS

Our next step is to set up an LVM structure within the LUKS container we just created. LVM stands for Logical Volume Manager: a useful overview may be found here, and a handy command cheatsheet here. It is a highly flexible virtual partition system. Some important LVM terminology is as follows:

  • A physical volume (PV) is an underlying storage device (for example, an actual disk partition or loopback file), which is managed by LVM. PVs have a special header, and are divided into physical extents.
  • A physical extent (PE) is the smallest allocatable unit of a PV. We will use the default PE size of 4MiB in this tutorial.
  • A logical volume (LV) is LVM's equivalent of a partition. It contains logical extents, which are mapped one-to-one onto the PEs of contributing physical volumes. Note - unlike a conventional partition, because of this architecture an LV can span multiple underlying physical volumes, and a physical volume can host multiple logical volumes, if desired. The LV appears as a standard block device, and so can be formatted with any normal Linux filesystem (e.g. ext4). We will create LVs for the root directory, the user home directory and swap in this tutorial.
  • A volume group (VG) is an administrative unit gathering together a collection of LVs and PVs. We will create a single VG containing a single PV, and (as just mentioned) three LVs.

The main reason we're using LVM here is to provide a simple way to get three 'logical' partitions on top of a single underlying LUKS container (partition). LVM also provides a number of additional advantages when resizing, backing up, or moving partitions, in exchange for a little initial configuration overhead.[9]

To proceed with LVM, the first thing we need to do is open the LUKS volume we just created, as it will host our single PV. Issue:

livecd ~ #gpg --decrypt /tmp/efiboot/luks-key.gpg | cryptsetup --key-file - luksOpen /dev/sdZn gentoo
Enter passphrase
<type the passphrase for the gpg keyfile you setup earlier>
... additional output suppressed ...
Replace /dev/sdZn in the above command with the device path for the LUKS partition, e.g., /dev/sda7.
Depending on how soon after last decrypting the gpg keyfile you issue the above command, you may find that you are not prompted for a passphrase at all. That's because your passphrase has been (temporarily) cached behind the scenes, for convenience, by gpg-agent. If you want to force the passphrase prompt (for example to double-check you have the passphrase written down correctly!), you can do so by issuing the following prior to the luksOpen command above:
livecd ~ #echo RELOADAGENT | gpg-connect-agent

Check that this worked:

livecd ~ #ls /dev/mapper
control  gentoo

You should see the device 'gentoo' in the device mapper list, as above. This is our unlocked LUKS partition.

Next, we'll create an LVM physical volume (PV) on this partition:

livecd ~ #pvcreate /dev/mapper/gentoo

Then, we create a volume group (VG) hosting this PV. We'll call the new VG "vg1". Note that since we're using lvm2 format here, there's no need to set a larger physical extent size - the default of 4MiB per PE will be fine [10]:

livecd ~ #vgcreate vg1 /dev/mapper/gentoo
Please use the suggested VG name (vg1), since this is assumed by the buildkernel utility later. If you do need to change it, you'll need to override CMDLINE_REAL_ROOT and CMDLINE_REAL_RESUME variables appropriately in /etc/buildkernel.conf later in the tutorial.

Now, we'll create three logical volumes (LVs) in this volume group. The first is for swap. To allow the use of suspend to disk (which we'll setup later) we'll want a swap slightly larger than the size of our RAM. So first, find the size of RAM on your system with:

livecd ~ #grep MemTotal /proc/meminfo

In the case of the CF-AX3, this shows just under 8GiB, hence we'll allocate 10GiB. Adjust this for your system and preferences. If you don't want to use suspend to disk, a much smaller swap would work just as well.

livecd ~ #lvcreate --size 10G --name swap vg1
LVM uses base-2 units, so this is 10GiB. Adjust the size to suit your system, as described above.
If lvcreate complains about not being able to wipe the start of the LV, try adding the -Z n parameter to the previous command. Supposedly it is dangerous to mount an LV whose first few kilobytes haven't been wiped, but then again, you'll be formatting your LV with a filesystem.

Next, we'll create a relatively large LV to hold our root partition. This will eventually hold everything apart from the user home directories, and, since this is Gentoo, we'll need a fair amount of room for portage files and so on. We'll allow 50GiB here - if you wish you can make this smaller or larger of course:

livecd ~ #lvcreate --size 50G --name root vg1
LVM uses base-2 units, so this is 50GiB. Adjust the size to suit your needs, as described above.

Finally, let's create a third LV to hold the user home directories. We'll instruct LVM to use almost all the remaining space on the LUKS container for this, leaving 5% of the (so far unused space) free (this additional room will come in useful if you want to take a snapshot[11] later, for example).

livecd ~ #lvcreate --extents 95%FREE --name home vg1

You should now be able to look at the status of the physical volume (PV), volume group (VG) and logical volumes (LVs), as follows:

livecd ~ #pvdisplay
livecd ~ #vgdisplay
livecd ~ #lvdisplay

The final task in this step is to 'activate' the new volume group (vg1) so that it's logical volumes become available as block devices via the device mapper. Issue:

livecd ~ #vgchange --available y

This should inform you that three LVs in the vg1 volume group have been activated. Check that they are visible via the device mapper:

livecd ~ #ls /dev/mapper
control  gentoo  vg1-home  vg1-root  vg1-swap

If your output looks similar to the above, then all is well. The new logical volumes (/dev/mapper/vg1-home, /dev/mapper/vg1-root and /dev/mapper/vg1-swap) can be treated exactly like physical disk partitions (i.e., just like /dev/sda1 etc.).

Formatting and Mounting the LVM Logical Volumes (LVs)

Now we have our virtual partitions, we need to set up their filesystems and then mount them.

First, create the swap:

livecd ~ #mkswap -L "swap" /dev/mapper/vg1-swap

Next, the root filesystem. We'll create this as ext4 (you can of course modify this if you wish):

livecd ~ #mkfs.ext4 -L "root" /dev/mapper/vg1-root

Finally, the user home filesystem, also ext4. Note that we use the -m 0 option here, since ext4 will, by default, reserve 5% of the filesystem for the superuser, and we don't need that in this location, only on the root partition:

livecd ~ #mkfs.ext4 -m 0 -L "home" /dev/mapper/vg1-home

Now, we activate the swap:

livecd ~ #swapon -v /dev/mapper/vg1-swap

And, per the handbook, mount the root directory at the pre-existing /mnt/gentoo mountpoint:

livecd ~ #mount -v -t ext4 /dev/mapper/vg1-root /mnt/gentoo

Next, we create the /mnt/gentoo/home mountpoint, a /mnt/gentoo/boot directory, and a /mnt/gentoo/boot/efi mountpoint. The purpose of these is as follows:

  • /mnt/gentoo/home will be the mountpoint for our home directory LV.
  • /mnt/gentoo/boot will be the equivalent of the /boot directory in the Gentoo handbook. We will build our kernel and initramfs targeting this directory as usual, although, since we are booting from an UEFI USB key, this directory will not be used when booting the system itself. Instead, the buildkernel utility, supplied as part of this tutorial, will be used to copy the final, signed and bootable kernel image onto the USB key (at /mnt/gentoo/efiboot) as part of the kernel build process. For that reason, we've converted /mnt/gentoo/boot from a mountpoint to a regular directory in this tutorial.
  • /mnt/gentoo/boot/efi will be the mountpoint for our USB boot key when inserted in the machine (when installing a new kernel, etc.). We currently have the key mounted at /tmp/efiboot and will need to unmount it.

Create the directories:

livecd ~ #mkdir -v /mnt/gentoo/{home,boot,boot/efi}

Now mount the "home" LVM logical volume from the "vg1" volume group on the /mnt/gentoo/home mountpoint:

livecd ~ #mount -v -t ext4 /dev/mapper/vg1-home /mnt/gentoo/home

Next, we need to unmount the USB boot key's EFI partition from its current temporary mountpoint (we'll remount it later, when we build the kernel):

livecd ~ #umount -v /tmp/efiboot

Finally, issue:

livecd ~ #blkid /dev/sdY1 /dev/sdZn
Replace /dev/sdY1 in the above with the actual path of your USB boot key's first partition, which we found earlier (e.g., /dev/sdc1 etc.), and /dev/sdZn with the actual device path for the LUKS partition (e.g., /dev/sda7 etc.).

Take note of the PARTUUIDs (unique partition identifiers) for these two partitions; we'll make use of them later (in the fstab and the kernel build script's configuration file), rather than relying on the /dev/sd?? paths (which can change depending on which devices are plugged in, and the order in which they are recognized).

Next Steps

We're now ready to fetch the additional installation files and setup the build options. Click here to go to the next chapter, "Installing the Gentoo Stage 3 Files".


< Previous Home Next >