Pages

03 March 2011

Arch linux installation guide: btrfs + encryption

I've been running Arch Linux for quite some time now, and I love it. For various reason I've been looking into disk encryption and finally took the plunge recently to get a fully encrypted system up and running. I decided to make a one-stop-shop for the process, partially to give a nice customized reference to myself, but also to help anyone else googling the subject. The Arch Wiki is great (I contribute!) but sometimes it's nice to have a separate reference. I often use the website as well as others' blog tutorials to fill in any missing pieces between one reference and another, or to see another way of doing something that might seem simpler or more appealing.

So... let's embark. I decided to give btrfs a try while I was in the business of re-installing, so that's covered here as well. It wasn't easy!


Preparation


You've surely heard it before... but the most important thing you can do before you start tinkering is to back up your data. Seriously, if you haven't done that... just take a deep breath, resolve to abandon whatever impatient and silly motives have convinced you that you need to do this now, at 2am, and go backup your stuff. To illustrate that I practice what I preach, I created a config directory in my home folder and copied any system configs I thought would be helpful upon reinstallation (conky.conf, rc.conf, 10-synaptics.conf, 10-monitor.conf, mkinitcpio.conf, and whatever else struck me) and then rsync'd my home folder to 1) my work network share and 2) an external hard drive. I try to keep two copies of data at all time. If you're wiping your computer... that means you need two other locations for things to reside.

If that's all covered, we can have some fun. Get a decently recent copy of the Arch install ISO; I recommend the netinstall version, but you'll need internet for that to work. Just go camp out by your router. Burn that to a CD and boot from it. I had an older-ish copy laying around and had issues with btrfs and perhaps something else... though I can't recall what. I do know that the older version used kernel 2.6.30, and that was too old for what I was trying to do (should have written down the issue). Downloading a new version worked great.

Next you're going to erase your hard drive. I did a pass of zeros using:
# dd if=/dev/zero of=/dev/sda bs=1M

Then, you'll want to generate random data if you're encrypting. This eliminates any chance of data being recovered or being able to identify where the data resides on the disk (you're creating "background noise" to mask the encrypted data amidst the disk's free space).
# dd if=/dev/zero of=/dev/urandom bs=1M

You can use /dev/random (will take muuuuch longer) or the badblocks method discussed on the wiki.

Alright. With your disk filled with random data, let's move on to partitioning and setting up encryption!


Partitioning & Encryption


Boot up from the install disk. If you have Intel based graphics, make sure you press the tab key from the "Boot Arch" option and add this to the end of the boot options:
i915.modeset=0

Kernel mode setting was made mandatory in kernel 2.6.32, and if you don't have the right modules loaded, you'll get a black screen when you should be seeing the login screen. There maybe another way to fix this, but the solution above is what I used and is discussed on the Arch wiki. We'll also cover how to build it into your initramfs later on for proper setup.

Once booted, log into the Arch installer with "root." Run "cfdisk" and partition your disk. I'm not covering that here, since it's covered far better and more plentifully elsewhere. All I did was to create two partitions: one for /boot and one for the rest of my system. My boot partition is 128M. Set the non-boot partition (or one of them) to bootable, write the table, and exit.

Now to setup encryption. You need to format your data partition(s) as encrypted space using cryptsetup. To access the right encryption tools, run:
# modprobe dm_mod

Now run some variant of this:
# cryptsetup -c -y -s luksFormat /dev/

This formats the partition as and encrypted device. Per the Arch wiki, I used the aes-xts-plain cipher, and a 512 bit key. Thus, my command looked like this:
cryptsetup -c aes-xts-plain -y -s 512 luksFormat /dev/sda2

For reference, I'm using /dev/sda1 for boot and /dev/sda2 is the rest of the drive. Use whatever partitions make sense for you in place of my commands.

You will then be prompted for a passphrase, and then again to confirm it. There are lots of other options covered in the Arch wiki about using keyfiles (like a file on a USB drive) so that the keyfile needs to be present at boot. You can always add more passwords and keyfiles later, though (HERE).

Once the partition is setup, we need to unlock/open it to be able to do anything with it. To do that, run this:
cryptsetup luksOpen /dev/sda2 root

This uses the passphrase you enter to unlock the partition for mounting. It uses a device mapper to make the unlocked partition available at /dev/mapper/root. That "root" at the end of the above command is a label. You can use whatever you want; then just access it via /dev/mapper/whatever-label-you-used).


Setup network


At this point you should set up your network. Plug into a router or access wireless somehow (I'm still not familiar with how to do that with protected wireless, so I always use unprotected or turn off my password temporarily on my own router and then use: ifconfig wlan0 up, iwconfig wlan0 essid router-name, dhcpcd wlan0).


Btrfs and manual installation


Next, I made a btrfs filesystem on /dev/sda2. If you don't do this, you can skip ahead to the automatic installation part (a lot less interesting). To do this, I followed most of a blog post I found HERE. It was quite difficult to find simple, clear-cut instructions on exactly how to use btrfs and set it up for installation, but what I did worked, so here goes...

You need btrfs filesystem tools first. Sync pacman and get them like so:
# pacman -Sy btrfs-progs-unstable

If you get flagged and asked to upgrade something else first (like pacman itself), go for it and then just rerun the above command (you can run it without the y flag).

Now create a new filesystem on /dev/mapper/root:
# mkfs.btrfs -L label-you-want /dev/mapper/root

Make a directory to mount /dev/mapper/root to:
# mkdir /broot

Mount it!
# mount -o noatime,defaults /dev/mapper/root /broot

Now we want to create some btrfs subvolumes. I went with the naming convention discussed at various places in the Arch forums and wiki as well as the blog I referenced above.
# btrfs subvolume create /broot/__active

And now we mount that:
# mount -o subvol=__active /dev/mapper/root /mnt

Then we can create some sub-subvolumes which will function like separate "partitions" in our btrfs pool:
# btrfs subvolume create /broot/__active/home
# btrfs subvolume create /broot/__active/usr
# btrfs subvolume create /broot/__active/var

Subvolumes are created with default permissions of 700; you'll want them to be 755. Run:
# chmod 755 /mnt/[dir]

for __active, __active/home, __active/usr, and __active/var.


I'm still not positive on exactly how this works since (as you'll see later) they aren't explicitly mounted in fstab. The blog post I followed as well as an Arch forum post (same author, I think) mentions that with btrfs, subvolumes of a higher level subvolume get mounted automatically.

I do believe this is the case, and with our current setup, the system will look likd this:
/
|-__active (main subvolume for working root)
  |- /bin
  |- /boot (/dev/sda1 mounted here)
  |- /dev
  |- /etc
  |- /home (separate subvolume)
  |- /lib
  |- /lib64
  |- /media
  |- /opt
  |- /proc
  |- /root
  |- /sbin
  |- /srv
  |- /sys
  |- /tmp
  |- /usr (separate subvolume)
  |- /var (separate subvolume)


I was wondering if /home, /usr, and /var were really mounted btrfs subvolumes or if they were just directories in __active. I put this to the test and did this (from my running system):
# mount /dev/mapper/root /mnt
# btrfs subvolume snapshot /home /mnt/home-snapshot
# btrfs subvolume list /mnt


This showed that home-snap was, indeed, a new subvolume at the top level, which confirmed that my active /home directory was actually a snapshot (trying to snapshot non-subvolumes doesn't work). So, be confident that whatever subvolumes you create under the top-level __active subvolume will function like it's own entity and let you have control over it for snapshots, rollbacks, or whatever else you want. While I haven't tried it yet, you may be able to pass separate mount options to these sub-subvolumes as well, though I have not been successful wtih anything like this:
# mount /dev/mapper/root -o subvol=__active/home /mnt

That gives an error for me. Perhaps one can only mount top level subvolumes? Anyway, I've gotten ahead of myself. Moving on, let's actually install Arch!

Pacman will complain about not having a directory to work in, so create it:
# mkdir -p /mnt/usr/lib/pacman

Also, mount your boot partition in the right place so that when we install the kernel and grub you get the right things in there (though it's no big deal to copy them later if you forget):
# mount /dev/sda1 /mnt/boot

Now run this and relax for a while:
# pacman -r /mnt -Sy base whatever-else-you-want

This will run pacman and install the base system. I'd add on some or all of these:
- base-devel (almsot a necessity)
- wireless_tools (I booted up the first time and didn't have iwconfig. Bummer.)
- btrfs-progs-unstable (you'll need this on the new system)

Once that's one, it's time to configure things. I think it's easiest to just chroot into the new system and use it so you just edit things normally (like /etc/rc.conf instead of constantly doing /mnt/etc/rc.conf). To do that, setup sys, proc, and dev:

mkdir /mnt/sys /mnt/proc /mnt/dev
mount -t proc /proc /mnt/proc
mount -o bind /dev /mnt/dev
mount -t sysfs /mnt/sys
chroot /mnt

We need to install the grub bootloader. On my system, the proper files were not in place to run grub setup, and in looking around I found instructions on how to get the right files in place on the wiki.
cp -a /usr/lib/grub/i386-pc/* /boot/grub/

Then manually install the bootloader to the MBR:
grub

which will open a grub shell. Then you need to point grub to the bootloader files. For me, this is on disk 1, partition 1. Since numbering starts at zero, this equates to:
root (hd0,0)

If you have several hard drives, alter the hd# bit. If it's a different partition, then change the second number after the comma. Now install the bootloader:
setup (hd0)

If this runs successfully, you're all set. I had some issues the first times I tried. If you need to troubleshoot, perhaps make sure that the partition you're using as a boot partition is mounted properly (if you're in the chroot, it should be at /boot relative to the chroot environment, which is really at /mnt/boot). You can also check to make sure that /boot/grub contains files like STAGE1 and STAGE2. Other than that... google is your friend.

While we're talking grub, edit /boot/grub/menu.lst so grub knows how to mount everything at boot. This is what my section looks like:
# (0) Arch Linux
title Arch Linux [/boot/vmlinuz26]
root (hd0,0)
kernel /vmlinuz26 cryptdevice=dev/sda2:root root=/dev/mapper/root rootflags=subvol=__active ro
initrd /kernel26.img


Do whatever you usually do, but make sure you have cryptdevice= and the rootflags= parts right.

Let's handle the next most important thing that's necessary to boot: building an initramfs that has the right options in it for encryption and btrfs. Edit /etc/mkinitcpio.conf:
# nano /etc/mkinitcpio.conf

For the modules section, you want to add intel_agp and i915 for the Intel kernel mode setting we talked about earlier, and crc32c for btrfs. The line should look like this now:
MODULES="intel_agp i915 crc32c"

Also, we need to add the encrypt hook to be able to mount the encrypted partition at boot. Scroll down and make the hooks section look like this:
HOOKS="base udev autodetect pata scsi sata encrypt filesystems"

Just make sure that encrypt is before filesystem. The above is just an example. I didn't do anything except add encrypt; the rest was just left alone.

We need to rebuild the initramfs with these new options now:
# mkinitcpio -k 2.6.37-ARCH -c /etc/mkinitcpio.conf -g /boot/kernel26.img

Moving on, let's edit fstab so everything gets mounted in the right place:
/dev/sda1 /boot none defaults 0 2
/dev/mapper/root / btrfs noatime,defaults,subvol=__active 0 0


Alright, that should handle the important stuff. Tackling the rest:

/etc/rc.conf
- edit your timezone
- set the hostname

/etc/locale.gen
- uncomment your locales (for example, uncomment both en_US.UTF-8 UTF-8 and en_US ISO-8859-1
- run # locaele-gen

/etc/hosts
- add the hostname you set in /etc/rc.conf to the end of both lines.

/etc/pacman.d/mirrorlist
- uncomment your preferred mirror

root password
- run passwd root and enter a password twice.

At this point, you should be able to reboot and give 'er a whirl. Exit out of the chroot, unmount stuff, and reboot!
# exit
umount /mnt/{dev,proc,sys}
umount /mnt
reboot


If all goes well, the system should run through some of the boot process and you should see a line asking for a password for /dev/sda#. If that happens, you're good to go!


Post install stuff


If you're already familiar with this stuff, you can probably go on your way. I add it here partly for myself, as having a record of my install process helps me have an all in one reference. For newer folks, it might help to have another user's process for comparison and to fill in any gaps (sometimes I just need to read something more than one way before I get it!).

Once up and running, add user for yourself. I use adduser and just follow the prompts. You probably want to add yourself to these groups: audio,lp,optical,storage,video,wheel,power.

My typical setup involves installing a whole lot of stuff and then adding various tidbits as I go. For example, I usually forget to setup alsa (sound) until I try to watch my first youtube video on a new system and don't know why I'm not hearing anything :)

In any case, I ended up installing yaourt by adding this to /etc/pacman.conf
[archlinuxfr]
Server = http://repo.archlinux.fr/x86_64 -> /etc/pacman.conf


and then running
pacman -Sy yaourt

Some other stuff you might want to install:
- xorg
- xf86-video-[your driver] (I install xf86-video-intel)
- touchpad driver (xf86-input-synaptics)
- a window manager (openbox for me, along with lxappearance and obconf)
- a panel (tint2)
- office suit (libreoffice)
- a terminal (rxvt-unicode)
- fonts (ttf-bh-font, ttf-bitstream-vera

Heck, I just tossed on all of the stuff I could think of for myself (texlive, libreoffice, wicd, rxvt-unicode, openbox, xorg, lxappearance, obconf, conky, tint2, ttf-bh-font, ttf-bitstream-vera, and whatever else came to mind).


Installing without btrfs


If you're not using btrfs and just doing encryption... just follow the the wiki and use the installer, paying attention to selecting /dev/mapper/root instead of /dev/sda2 for the root partition. The installer is quite simple, makes sure you remember what files to edit and so on. I think it's possible to do this with btrfs (by just mounting things in the right places ahead of time... but I didn't do it that way).

10 comments:

Anonymous said...

"fully encrypted system" does'nt include /boot (which seems to stay on unencrypted /dev/sda1) for you ?

rufflove said...
This comment has been removed by the author.
rufflove said...

Nice writeup - I used it to set up an install on a USB stick. I also installed kernel26-pf, compressed /usr and set up ramlog during the process and was honestly surprised find it all worked on first boot, without any trouble shooting. However, it would've been helpful if I'd remembered to add usbinput to the mkinitcpio hooks... ;)

Thanks again

Hendy said...

@anonymous: not at present because I don't know how to encrypt /boot with Linux. Other than someone trashing my system, I guess I don't see a whole lot of need for an encrypted /boot partition, or perhaps I don't know something I should! Could you clarify why someone might want an encrypted /boot? Is there anything "hackable" re. dm-crypt in there?

Re. destroying my system by tinkering with /boot... I could do the same to an encrypted system as well. Boot up a live CD and "dd if=/dev/urandom of=/dev/sda bs=512 count=1" or anything of the sort to the various partitions. It doesn't take much to screw up an encrypted header and make it unrecognizable.

@rufflove: Awesome! Glad I could help. I stopped doing this because my drive ran into serious trouble with btrfs. I experienced the famous no free space left issue. All of the sudden any method of determining free space came up with absolutely nothing. I wiped, had to start over, and went with EXT4. Bummer!

Hendy said...

@rufflove: Oh, and I did the same thing with a previous distro once! I made a bootable flash drive and couldn't get it to boot for the life of me... I was using Zenwalk at the time, and didn't use an initramfs, so it came down to compiling a custom kernel and building in [O/E]HCI into the kernel so it could boot! Same idea with adding it to the mkinitcpio, though. Glad you're up and running!

C Anthony [xtfxme/extofme] said...

nice :)

a couple quick notes off top-o-head:

) snapshots are NOT recursive, so by having nested subvols you cant take a fully consistent snap (AFAIK) ... which isnt neccesarily a problem, just something to be aware (you could maybe use fsfreeze ... untested ...)

) __active was an arbitrary choice i figured would not collide with any existing directories ... what's important is that you DO NOT install into the "btrfs root" because then you lose a lot of control ... you cannot manipulate the btrfs-root (move/del/etc) like you can a subvol -- in short, use subvols for system roots/dirs, and use the btrfs-root for *management* of those subvols.

) yes, subvols must be in the "btrfs root" to mount by name. however, while you can't do:

mount /dev/mapper/root -o subvol=__active/home /mnt

... starting in 2.6.39 you CAN do:

mount /dev/mapper/root -o subvolrootid=,subvol=home /mnt

per: http://thread.gmane.org/gmane.comp.file-systems.btrfs/9991 ... so, to mount by name, a subvol must still by in the root of another subvol, but now you can at least specify a different root to search (likely 256 if __active was the first one you created). this would let you mount each with different opts (or alternatively you could just use subvolid= to mount the subvol directly :)

) this setup should work fine with a single disk, and i don't know much about encrypting whole disks ... but the `btrfs` hook or similar is needed for multi-device setups in order to probe devices. this may not be necessary in future (move to kern mod?), i dont know.

thats all i got :)

C Anthony

Hendy said...

@C Anthony: thanks for the tips! I am extreeeemely new to btrfs and this was more of an experimental endeavor. I really hope it comes along, as the feature set sounds fantastic and many rave about it. I was attacked by the out-of-freespace issue, and should they ever fix that, I may seriously re-consider. I'll also try to re-learn more about it's features and how to get the most from it. You obviously know quite a bit, so thanks for putting these corrections in here for others passing by!

Pgp software said...

There maybe another way to fix this, but the solution above is what I used and is discussed on the Arch wiki. We'll also cover how to build it into your initramfs later on for proper setup.

Pgp encryption said...

Hey,
I just hopped over to your site via Stumbleupon. Not somthing I would normally read, but I liked your thoughts none the less. Thanks for making something worth reading.


Hendy said...

@Pgp encryption: thanks for the comments, and I'd love a wiki update :) This is relevant to me again, as in getting a new (but used) ThinkPad recently, I decided to re-look into btrfs and am running it. After I ran into the famed free-space issues on my dual-boot Macbook, I re-installed fresh to ext4 and gave up.

1.5 years later I decided to give it another shot and I'm glad I had this post to refer back to!

Post a Comment

<i>, <b> | links: <a href=""></a>