Encrypted root With LVM on Fedora 8
Overview
This recipe details how you can install F8 (and most likely also F7
and CentOS 5) on a system such that everything except /boot is encrypted.
This recipe makes use of your full disc (no unused space is left after it's
completed), and doesn't require booting into a Live DVD (important because
many of my machines don't have DVD drives on them, many don't even have CD
drives). It also does not require a second hard drive.
I think this procedure is one of the easiest to do, and doesn't
require any resources to do beyond what a normal install would require.
The end result is the same as what you would get if you had done a normal
install using LVM for the root and swap. It also supports hibernation to
an encrypted swap partition. Installation can be done via PXE as well as
from the DVD.
Introduction
Stories abound about laptops being lost, and data possibly exposed
because of it. I'm also concerned about someone breaking into my house and
stealing our backup server, and through that exposing sensitive or
confidential client data for many of our customers. I'm actually not that
worried about the loss of the machines, they're cheap computers and data on
our home backup server is duplicated at our facility. So, I like to run
encrypted file-systems.
The benefits are huge. It's very convenient, you don't have to
encrypt and decrypt things as you need the. Though I still do encrypt
particularly sensitive data (ssh keys, access information), it's nice to
know that the loss of my laptop is unlikely to reveal sensitive information
that I don't normally think of as high security (and therefore specifically
encrypt). I don't have to worry about leakage of things that can reveal
more information than I'd like about our customers and clients, and our
business.
Of course, it's not an end-all security mechanism. You absolutely
have to protect your system to prevent access to the unencrypted
file-system. For example, keeping up to date on patches, and locking or
hibernating your computer when you are away from the keyboard... For
example, I always type Ctl-Alt-L when I leave my keyboard, or before I
suspend, to make sure that if someone were able to get to it they don't
have access to my sessions.
Before you Begin
Note that in the below instructions it assumes that you will be
installing to a whole disc (wiping anything else that was on the system).
These procedures should be able to be adapted to a dual-boot system, but I
don't run any dual boot systems, so someone else will need to provide
"patches" to this procedure for such a thing.
This recipe also assumes that your disc is named "sda". If your disc
is named something else, you will have to adapt the information below.
Severe Data Loss Warning
This procedure wipes everything on your current disc, if you follow
them exactly. Additionally, if you forget your pass-phrase, any data on
your system is gone. Any important data you have should be backed up in at
least several locations.
Step One: Formatting the Disc
The first thing that needs to happen is to partition the disc. The
installer partitioning software doesn't have the flexibility to be able to
do this, so you'll need to boot into the installer.
Once in the installer, you should be able to use Ctl-Alt-F2 to get a
root prompt. Then run:
fdisk /dev/sda
You need to create an "sda1" which is around 100MB, has the boot flag
set, and is of type 83 (Linux), and "/dev/sda3" which is around 10GB (but
less than half the remaining space on the drive), and is at the end of the
disc, and partition type 8e (Linux LVM). When done, it should look
something like:
Device Boot Start End Blocks Id System
/dev/sda1 * 1 13 104391 83 Linux
/dev/sda3 29000 30401 11253532 83 Linux LVM
I just tried a few different starting values for sda3, to get around
11GB. Though sda3 doesn't have to be at the absolute end of the disc, it
hast to have an unallocated space slightly larger than it right before it.
So if you wanted to make it 5GB you could create a sda2 right after sda1,
and use "+6G" for the size of sda2, then do the "+5GB" for sda3,
then delete sda2.
We will be later creating sda2 and resizing it to use all additional
space on the disc, that's why sda3 needs to be created after sda2 and sda2
needs to have slightly more space than sda3 (to hold the contents of sda3
as well as the LUKS information).
Once done, write the partition table and reboot the system.
Step Two: Installing the OS
The installation
must be done using the graphical
installer, because the text installer doesn't allow a custom installation
to use LVM.
For the partitioning, select "Custom", and tell it to format sda1 as
/boot, and sda3 as an LVM physical partition.
Then use the "LVM" button to create a volume group, and a logical
volume within it for the "/" file-system. You can also create swap or
other LVM partitions if you like. Note that you'll be able to resize the
partitions later, so they don't need to be the desired target space or
proportion right now.
The default volume group name should be used, or you will need to
substitute "VolGroup00" for your name in the rest of this recipe.
After the partitioning, the rest of the installation can be done as
normal.
Step Three: Create sda2
Boot into the installed system and create sda2 using fdisk. It needs
to be the space between sda1 and sda3, and it should have a partition type
of 83 (Linux) (it does not need to be type 8e, Linux LVM).
Reboot the system to get it to recognize the new partition.
Step Four: Set up encrypted partition
You now need to set up the encrypted partition, using the command:
cryptsetup --key-size 128 --verbose --verify-passphrase --cipher \
aes-cbc-essiv:sha256 luksFormat /dev/sda2
It will ask you to confirm you want to destroy all data on the
partition, and then will ask for a pass-phrase. You will need to remember
this pass-phrase for future use of your system.
Step Five: Fix system to properly build initrd
Add the following line to "/etc/sysconfig/mkinitrd" (which may not
already exist:
MODULES="aes sha256 dm_crypt cbc"
This tells mkinitrd that you will need these modules. If there is
already a "MODULES=" line, you will need to add the above modules to that
line.
The "/sbin/mkinitrd" file needs to be updated as well. I hate to do
it, but I just end up modifying the file in-place. Future updates of this
package will overwrite it, but at least these changes will cause future
kernel updates to properly build an initrd.
So, apply this patch (
available
via FTP) to "/sbin/mkinitrd":
*** mkinitrd.orig Mon Nov 19 06:19:24 2007
--- mkinitrd Mon Nov 19 06:20:06 2007
***************
*** 1317,1322 ****
--- 1317,1323 ----
inst /sbin/insmod "$MNTIMAGE" /bin/insmod
inst /sbin/rmmod "$MNTIMAGE" /bin/rmmod
+ inst /sbin/cryptsetup "$MNTIMAGE" /bin/cryptsetup
if [ -e /etc/fstab.sys ]; then
inst /etc/fstab.sys "$MNTIMAGE"
***************
*** 1540,1545 ****
--- 1541,1549 ----
done
fi
+ emit "echo Decrypting root device"
+ emit "cryptsetup luksOpen /dev/sda2 lvm"
+
if [ -z "$nolvm" -a -n "$vg_list" ]; then
emit "echo Scanning logical volumes"
emit "lvm vgscan --ignorelockingfailure"
Step Six: Build new initrd
Move the existing initrd to the same name, but ending in ".old".
We will be booting using the old initrd in a bit, so don't get clever and
delete it instead of making a new one... For example:
cd /boot
mv initrd-2.6.23.1-42.fc8.img initrd-2.6.23.1-42.fc8.img.old
Now, run mkinitrd with the path to the initrd and kernel version, for
example:
cd /boot
mkinitrd initrd-2.6.23.1-42.fc8.img 2.6.23.1-42.fc8
Step Seven: Reboot into init=/bin/sh and copy data
Boot the system using the old initrd, and adding "init=/bin/sh" to
boot the system into a minimal environment (the root file-system isn't even
mounted read/write).
In GRUB, use "e" to edit the boot options.
Use the down arrow to move to the initrd line and type "e" to edit
the initrd to append ".old" to the name.
Use the arrow keys to select the kernel line (probably the line above
the initrd line) and use "e" to append a <space> and "init=/bin/sh".
Press "b" to boot into this mode. You should get to a root prompt
fairly quickly, with no errors.
Step Eight: Copy the LVM to the encrypted partition
Open the encrypted file-system with:
/sbin/cryptsetup luksOpen /dev/sda2 lvm
Enter your pass-phrase. Now you can copy the sda3 to the encrypted
sda2:
dd if=/dev/sda3 of=/dev/mapper/lvm
This may take a while, especially on a slow laptop. I recently did a
5GB partition on an slower laptop and it took a good half hour to copy.
When it's done, close the encrypted partition with:
/sbin/cryptsetup luksClose lvm
Step Nine: Remove the old LVM partition
We must remove sda3 before rebooting, so that it isn't used during the
reboot. We might as well re-partition it so that sda2 is the full size of
the disc as well.
Run:
fdisk /dev/sda
Use the "p" command to print the current partition table and make note
of the existing sda2 and sda3 start and end. This will be useful if you
have made any mistakes, you can restore the partition table if it doesn't
reboot properly, and use the ".old" initrd to boot into the non-encrypted
LVM to try to fix things.
Now delete sda3 and sda2, and re-create sda2 with the same starting
block, and a larger size. I just use the defaults, so it creates sda2 as
the full remaining size of the disc except for sda1.
Write the changes to the partition table.
Step Ten: Reboot
At this point you should be able to do Ctl-Alt-Del and reboot the
system. It should ask you for your pass-phrase, then the system should boot
as normal.
Step Eleven: Resize the root file-system
I'm just running with a single large root partition. So, when I'm
done with the above I want to extend the size of the root partition.
Though you can create new logical volumes (for swap or other partitions) or
extend other existing partitions similarly.
We need to resize the crypto device first with:
cryptsetup resize lvm
This will detect the new partition size (resized before the reboot)
and resize the crypto device.
Now we need to resize the physical volume in the volume group:
pvresize /dev/mapper/lvm
You can find the existing size of your logical volume by looking at
the output of "lvdisplay" under the "Current LE" line for the partition you
want to increase the size of. That's the logical extents. Each logical
extent is 32MB, probably, so a 5GB partition would have around 150 LE.
Next, you can find out how many physical extents are available by
running "vgdisplay" and seeing the "Free PE" line. You can add up to this
many physical extents to your logical volume. So, take the current number
of logical extents, add to it the number of physical extents you want to
add, and use it in the "-l" option in:
lvextend -l 900 /dev/VolGroup00/LogVol00
Again, this assumes that your volume group is named VolGroup00, and
that the partition you want to extend is named "LogVol00". See the "df"
output for information on what this may actually be named. Note that you
can also use a more symbolic size with "-L", for example "-L 30G" instead
of the "-l 900" above
I usually want to make my root partition the full size of the device,
which is hard to do with the symbolic name. So, I just get the current
Logical Extent number, add to it the free Physical Extents, and resize it
to use all of them.
Now, resize the file-system with:
resize2fs /dev/VolGroup00/LogVol00
This will take several minutes, and while running if you do "df" in
another window you will see the file-system growing in size.
Wrapping Up
So you now should have a full-disc, with the exception of /boot,
encrypted logical volume. Future kernels should build an initrd that
automatically includes the encryption code, so updates shouldn't break
anything.
Enjoy.