As I said before, the laptop came with Windows 8 preinstalled, and the following partition scheme:
/dev/sda - SSD, 62.5 GB, GPT partition table
/dev/sda1- 500 MB - Windows recovery
/dev/sda2- 100 MiB - EFI System Partition
/dev/sdb3- 128 MiB - Windows reserved
/dev/sda4- 1 GiB - “RPC_RP” (???, VFAT, looks like something related to Windows bootloader)
/dev/sda5- 60.5 GB -
/dev/sdb - HDD, 1 TB, MBR partition table
/dev/sdb1- 869 GiB -
D:“Data” (empty NTFS)
/dev/sdb2- 60.5 GiB -
E:“Recovery” (NTFS with installers for all OEM-provided drivers and tools, images of some partitions on /dev/sda)
Now, for some reason, I don’t feel like wiping Win8. Maybe it’s because
I wanna try out Win10 once it’s out, or maybe I’m afraid one day I’ll need to use some windows-only program for school/work/etc. Whatever the reason is, I’ll go for dual-boot.
Move over, you fat Windows!
First of all, on Windows I deleted/uninstalled any useless crap from
C: that was taking significant amount of space, disabled hibernation (to get rid of the huge
hiberfile.sys) and configured swap to only use
D:. Then I shrank
C: down to 32,9 GiB. There’s still some free space on it, but unmovable files of a recovery point (which I’m hesitant to delete) prevent further shrinking. That leaves 24,9 GiB free SSD space for Linux, which is more than enough for my purposes. Then I shrank
D: to 100 GiB. Unfortunately, Windows can only resize partitions by moving the end, which resulted in the fastest 100 GiB of the HDD occupied by a partiton meant for stuff like music and videos (at least that’s my plan). I moved it later, but first…
Step back MBR, and look at the power of GPT
… but first I decided to boot Archiso and convert the /dev/sdb’s partition table to GPT. Because GPT is superior, and I might need more than 4 partitions, etc. (Later it turned out it was a great idea for one more reason.)
So I did a
gdisk /dev/sdb as the tutorial says, checked that there’s no warnings, printed the in-memory partition table and made sure the partitions begin and end at the same sectors than in the original partition table (printed with
fdisk -l /dev/sdb), and hit
write. And it worked. The partiton table was GPT, and all the partitions were still visible both under Linux and under Windows.
Now to move the 100GiB NTFS partition…
Ok, so I created a new 100GiB partition (
/dev/sdb3) with gdisk at the end of the disk, right before the 60,5GiB
/dev/sdb2. It’s partition type in GPT was gdisk’s default - “Linux filesystem”. Then I copied the old NTFS filesystem from
/dev/sdb1 to the new partition
ddrescue, putting the log on an USB stick (I don’t think I really needed the log, but this way, in case of power loss, I could resume the copying instead of starting from scratch). IIRC the copying took like 30-40 minutes. Then I rebooted to Win8 and saw that it still recognizes
D:, and doesn’t care about
/dev/sdb3, most likely because of its type in GPT. Rebooted to Archiso, and changed partition types in GPT:
/dev/sdb1/’s to “Linux filesystem” and
/dev/sdb3’s to “Microsoft basic data” (note: they’re actually GUIDs, but I reference them by the captions gdisk uses to represent them). Then I rebooted to Win8, and - as expected - it now recognized
D:, and all the files I had put there were still there, and swap seemed to work ok. Finally, I deleted
/dev/sdb1 Dunno if it would’ve gone this smoothly, if it had been still on MBR partition table.
At that point I had all the space I needed on /dev/sdb for Linux partitions.
On the SSD
/dev/sda I created a single
/dev/sda6 “Linux filesystem” partition out of all the remaining free space. On the HDD I created a 16 GiB
/dev/sdb1 type “Linux swap” at the beginning of the disk, then 1 GiB
/dev/sdb4 “Linux Reserved” right after swap (why? You’ll see later) and then
/dev/sdb5 “Linux filesystem” covering all the free space in the middle. Then I sorted the partition table with gdisk, so that the partition numbers reflect the on-disk order.
sdb2 (“Linux reserved”),
sdb3 (“Linux filesystem”),
E:). Rebooted to Win8, made sure it still correctly assigns partitions to disk letters, and then rebooted back to Archiso.
dd if=/dev/zero of=/dev/sdbX bs=4096 (yeah, my HDD has physical sectors of 4096 bytes, so IO is faster if you read/write a multiple of 4096 bytes).
sdb4 was over 700 GiB, so it took ~2 hours. But I don’t wanna risk someone suspecting my free disk space of being some encrypted hidden volume. And what I just said makes sense, because the next thing I did was shrinking
sdb3 to 25 GiB and
sdb2 to 2 MiB. (Actually, for each of them, I had to delete the partition and re-create it with new size, because neither fdisk/gdisk nor the recent versions of parted support a ‘rezise’ operation.)
But Wolf, what is your plan?
The plan was to have a LUKS-encrypted root partition on
/dev/sda6 (SSD), and then
/home on LVM on plain dm-crypt on the HDD. But since you can’t reliably delete anything from an SSD (because Flash Translation Layer likes to hide stuff from you(section 5.19)), I decided to use a detached LUKS header on the HDD. That’s what the 2 MiB
sdb2 is for. Now, I didn’t like the idea of offsetting everything by 2 MiB just because LUKS - things look much better when aligned to 1 GiB - so I left a 1022 MiB of unallocated space between
/var I anticipate a need for about 10 GiB and 15 GiB respectively (the latter due to Docker), which means a total 25 GiB for the LVM container (yeah, I know I didn’t take the LVM metadata into account). I can later expand the container to the free space following it, and allocate the extra extents to whichever logical volume (
/var) needs it.
Oh, and the existing
sda2 EFI System Partition will serve as
/boot, it has about 74 MiB free, which should be enough for a bootloader and even 2 sets of kernel,initramfs,initramfs-fallback (where initramfs-fallback is an initramfs with all the kernel modules, just in case).
The step I forgot
I should have filled
sdb3 with random data (eg. by mounting plain dm-crypt with random key on them and zeroing the mapped volume) before proceeding to the next step. This can reveal fs usage patterns. (Actually, it doesn’t matter for
sda6 because I
--allow-discards, and as for
sdb3, I don’t think it’s that big of a deal.) I’ll try to remember about it the next time I setup a dm-crypt (not too soon, I guess).
dm-crypt, LVM, mkfs
I did a
cryptsetup benchmark, and the results (for the ciphers) were:
# Algorithm Key Encryption [MiB/s] Decryption [MiB/s] aes-cbc 128b 667,8 2928,4 serpent-cbc 128b 90,2 580,4 twofish-cbc 128b 189,0 369,7 aes-cbc 256b 492,2 2178,7 serpent-cbc 256b 91,7 580,1 twofish-cbc 256b 190,3 369,5 aes-xts 256b 2517,5 2505,3 serpent-xts 256b 580,3 563,9 twofish-xts 256b 358,7 364,5 aes-xts 512b 1941,6 1936,3 serpent-xts 512b 582,1 563,9 twofish-xts 512b 359,5 364,1
As you can see, AES is much faster than the others on my hardware (probably because it has hardware acceleration on the CPU instruction set level), and XTS ciphers are about 5x faster at encryption than CBC (IIRC CBC can be parallelized only on decryption, not on encryption, so that migh be the reason). Moreover, XTS was designed with disk encryption in mind, so I decided to go with
aes-xts. More precisely,
aes-xts-plain64 (apparently XTS doesn’t need ESSIV(section 5.15)). As for key size, XTS actually splits the key in half, cause it needs two keys, so a 512 bit XTS key has strength equivalent to 256 bit symmetric key in other situations. While the strength of 128 bits “practically unbreakable” sounds good, 256 bits “breaking would require all the energy in Solar System” sounds better. So I went with 2x256 = 512 bit XTS key.
First, LUKS header for
cryptsetup luksFormat -c aes-xts-plain64 -s 512 --use-random --header /dev/sdb2 /dev/sda6
cryptsetup open --type luks --header /dev/sdb2 --allow-discards /dev/sda6 root
which opens the container as
Why did I use
--allow-discards ? Aren’t discards bad? Well, I think disclosing filesystem write patterns on files which are rarely written (like stuff in /usr and /etc), mounted with
relatime (atime updated only when mtime or friends are uptaded), isn’t that big of a deal, and can be sacrifised in order to extend the life of SSD. AFAIK, in case of my rationale for using dm-crypt on
/, which is making it harder to tamper with the filesystem and protecting plaintext keys (like sshd host keys in
/etc), it shouldn’t make a difference.
Now, to proceed with
sdb3, we need a place to store its key, so I made an ext4 fs on
mkfs.ext4 -L arch-root /dev/mapper/root
-L sets the label to
Then, after mounting
/mnt, I made a random 512 byte key for
head -c 512 /dev/random > /mnt/bundle-dm.key
wait, what? I made it 512 bytes instead of 512 bits? Whatever… it’s hashed anyway.
It should’ve been
head -c 64, but 512 bytes works too :P
And opened it:
cryptsetup open --type plain -c aes-xts-plain64 -s 512 --key-file /bundle-dm.key /dev/sdb3 bundle
and it should appear as
/dev/mapper/bundle. (don’t ask me why
bundle, I had no other idea for a meaningful name)
Then I created an LVM volume group on it:
vgcreate --clustered n -s 16M bundlevg /dev/mapper/bundle
--clustered nexplicitely tells LVM that no other computers in a cluster (there’s no cluster) will access the same volume (dunno if I really need it)
-s 16Msets the physical extent size to 16 MiB. The default is 4 MiB, and with LVM1 that would limit logical volume size to 256 GiB. LVM2 has no such limit, but the manpage says a large number of extents slows down the LVM tools (but not the IO performance). I thought setting the extent size to 16 MiB would be a good idea, because that would allow me to have 1 TiB in each logical volume even with LVM1, which means the number of extents won’t get crazy high. I hope that makes sense.
/var (i.e. a 15 GiB
/dev/mapper/bundlevg-var allocated from
bundlevg volume group)
lvcreate -L 15G -n var bundlevg
/home taking the remaining space:
lvcreate -l 100%FREE -n home bundlevg
and ext4 filesystems:
mkfs.ext4 -L var /dev/mapper/bundlevg-var
mkfs.ext4 -L home /dev/mapper/bundlevg-home
Finally, made mountpoints and mounted all the things:
mkdir /mnt/home mkdir /mnt/var mkdir /mnt/boot mount /dev/mapper/bundlevg-home /mnt/home mount /dev/mapper/bundlevg-var /mnt/var mount /dev/sda2 /boot
At this point, the filesystems are ready for ArchLinux instllation.