Manjaro on the RPI4 with full disk encryption
The Raspberry PI has become more and more powerful in the recent years, maybe too powerful to be a “maker board”. The higher CPU power and availability of more memory - up to 8GB - makes it more suitable for home server usage.
The latest firmware (EEPROM) enables booting from a USB device. To enable USB boot the EEPROM on the raspberry needs to be updated to the latest version and the bootloader that comes with the operating system - the start*.elf, etc files on the boot filesystem - needs to support it.
I always try to use filesystem encryption. You’ll find my journey to install GNU/Linux on an encrypted filesystem below.
64 Bits operating systems
The Raspberry PI 4 has a 64 bits CPU, the default operating system - Raspberry Pi OS (previously called Raspbian) - for the Rasberry PI is still 32 bits to take full advantage of the 64bits CPU a 64 bits operating system is required.
You’ll find an overview GNU/Linux distributions for RPI4 below.
-
Raspberry PI OS
Raspberry PI OS is the default operating system for the Raspberry Pi. The operating system is 32 bits.
There is a beta version available with 64 bits support available.
-
Ubuntu
Ubuntu for the raspberry pi has 64 bits support. But boot process isn’t fully compatible with USB boot. The bootloader isn’t up-to-date enough to support it and the u-boot loader isn’t yet updated to support USB boot.
-
Kali Linux
Kali Linux is another 64 bits operation system for the Raspberry Pi. The bootloader isn’t updated enough to support USB boot.
-
Arch Linux ARM
Arch Linux ARM has an install image for the Raspberry PI 4 the default install image is still 32 bits. Arch Linux ARM has 64 bits support so you could build you own image with the 64bits packages and a custom kernel.
-
Manjaro
Manjaro is based on Arch Linux and has 64 bits support for the raspberry pi. Manjaro is a rolling distribution the boot loader is up to date enough to support USB boot.
-
Other
The list above are the GNU/Linux distributions that I considered for my Raspberry Pi 4. There are - as always - other options. The distributions that don’t support booting from a USB device will probably support it soon.
I was looking for a GNU/Linux distribution with 64 bits support and USB boot support and went with Manjaro.
The installation process to install Manjaro on an encrypted filesystem is similar to the installation on an x84_64 system running Archlinux. See my previous blog posts: Install Arch on an encrypted btrfs partition and Install Parabola GNU/Linux on an Encrypted btrfs logical volume.
USB boot
To enable the raspberry pi 4 to boot from USB, you need to update your firmware. The boot loader also needs to be updated to enable booting from a USB device.
Get the latest firmware
Manjaro didn’t include the latest stable firmware to enable USB boot, so I used the 64 bits beta Raspberry PI OS to update the firmware.
Update Raspberry PI OS to get the latest firmware.
pi@raspberrypi:~ $ sudo apt-get update
Hit:1 http://archive.raspberrypi.org/debian buster InRelease
Hit:2 http://deb.debian.org/debian buster InRelease
Hit:3 http://deb.debian.org/debian-security buster/updates InRelease
Hit:4 http://deb.debian.org/debian buster-updates InRelease
Reading package lists... Done
pi@raspberrypi:~ $ sudo apt-get full-upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
pi@raspberrypi:~ $
Verify that the latest firmware is available.
The latest stable bootloader is located at /lib/firmware/raspberrypi/bootloader/stable
.
pi@raspberrypi:~ $ cd /lib/firmware/raspberrypi/
pi@raspberrypi:/lib/firmware/raspberrypi $ ls
bootloader
pi@raspberrypi:/lib/firmware/raspberrypi $ cd bootloader/stable/
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $
Verify that the pieeprom > 2020-06-xx is available.
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $ ls -l
total 1220
-rw-r--r-- 1 root root 524288 Apr 23 17:53 pieeprom-2020-04-16.bin
-rw-r--r-- 1 root root 524288 Jun 17 11:15 pieeprom-2020-06-15.bin
-rw-r--r-- 1 root root 98148 Jun 17 11:15 recovery.bin
-rw-r--r-- 1 root root 98904 Feb 28 15:41 vl805-000137ad.bin
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $
Get the current version
Execute vcgencmd bootloader_version
to get the current firmware version.
Please note that I already updated the firmware in the output below.
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $ vcgencmd bootloader_version
Jun 15 2020 14:36:19
version c302dea096cc79f102cec12aeeb51abf392bd781 (release)
timestamp 1592228179
update
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $ sudo rpi-eeprom-update -d -f ./pieeprom-2020-06-15.bin
BCM2711 detected
VL805 firmware in bootloader EEPROM
BOOTFS /boot
*** INSTALLING ./pieeprom-2020-06-15.bin ***
BOOTFS /boot
EEPROM update pending. Please reboot to apply the update.
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $
Reboot.
pi@raspberrypi:/lib/firmware/raspberrypi/bootloader/stable $ sudo reboot
Verify the version again.
pi@raspberrypi:~ $ vcgencmd bootloader_version
Jun 15 2020 14:36:19
version c302dea096cc79f102cec12aeeb51abf392bd781 (release)
timestamp 1592228179
pi@raspberrypi:~ $
The Raspberry PI is ready to boot from USB.
Install Manjaro on an encrypted filesystem
Manjaro will run an install script after the RPI is booted to complete the installion.
- We have two options boot the pi from the standard non-encrypted image and extract/move it to an encrypted filesystem.
- Extract the installation image and move the content to an encrypted filesystem.
You’ll find my journey of the second option below. The host system to extract/install the image is an x86_64 system running Archlinux.
Download and copy
Download and verify the Manjaro image from: https://www.manjaro.org/download/#raspberry-pi-4.
Copy the image to keep the original intact.
[root@vicky manjaro]# cp Manjaro-ARM-xfce-rpi4-20.06.img image
Create tarball
Verify the image
Verify the image layout with fdisk -l
.
[root@vicky manjaro]# fdisk -l image
Disk image: 4.69 GiB, 5017436160 bytes, 9799680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x090a113e
Device Boot Start End Sectors Size Id Type
image1 62500 500000 437501 213.6M c W95 FAT32 (LBA)
image2 500001 9799679 9299679 4.4G 83 Linux
[root@vicky manjaro]#
We’ll use kpartx
to map the partitions in the image so we can mount them.
kpartx is part of the multipath-tools
.
Map the partitions in the image with kpartx -ax
, the “-a” option add the image, “-v” makes it verbose so we can see where the partitions are mapped to.
[root@vicky manjaro]# kpartx -av image
add map loop1p1 (254:10): 0 437501 linear 7:1 62500
add map loop1p2 (254:11): 0 9299679 linear 7:1 500001
[root@vicky manjaro]#
Create the destination directory.
[root@vicky manjaro]# mkdir /mnt/chroot
Mount the partitions.
[root@vicky manjaro]# mount /dev/mapper/loop1p2 /mnt/chroot
[root@vicky manjaro]# mount /dev/mapper/loop1p1 /mnt/chroot/boot
[root@vicky manjaro]#
Create the tarball.
[root@vicky manjaro]# cd /mnt/chroot/
[root@vicky chroot]# tar czvpf /home/staf/Downloads/isos/manjaro/Manjaro-ARM-xfce-rpi4-20.06.tgz .
Umount.
[root@vicky ~]# umount /mnt/chroot/boot
[root@vicky ~]# umount /mnt/chroot
[root@vicky ~]# cd /home/staf/Downloads/isos/manjaro/
[root@vicky manjaro]# kpartx -d image
loop deleted : /dev/loop1
[root@vicky manjaro]#
Partition and create filesystems
Partition
Partition your harddisk delete all partitions if there are partition on the harddisk.
I’ll create 3 partitions on my harddisk
- boot partitions of 500MB (Type c ‘W95 FAT32 (LBA)’
- root partitions of 50G
- rest
[root@vicky ~]# fdisk /dev/sdh
Welcome to fdisk (util-linux 2.35.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x49887ce7.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-976773167, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-976773167, default 976773167): +500M
Created a new partition 1 of type 'Linux' and of size 500 MiB.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (1026048-976773167, default 1026048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1026048-976773167, default 976773167): +50G
Created a new partition 2 of type 'Linux' and of size 50 GiB.
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (105883648-976773167, default 105883648):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (105883648-976773167, default 976773167):
Created a new partition 3 of type 'Linux' and of size 415.3 GiB.
Command (m for help): t
Partition number (1-3, default 3): 1
Hex code (type L to list all codes): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.
w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Command (m for help):
Create the boot file system
The raspberry pi uses a FAT filesystem for the boot partition.
[root@vicky ~]# mkfs.vfat /dev/sdh1
mkfs.fat 4.1 (2017-01-24)
[root@vicky ~]#
Create the root filesystem
Overwrite the root partition with random data
Because we are creating an encrypted filesystem it’s a good idea to overwrite it with random data.
We’ll use badblocks
for this. Another method is to use “dd if=/dev/random of=/dev/xxx”, the “dd” method is probably the best method but is a lot slower.
[root@vicky ~]# badblocks -c 10240 -s -w -t random -v /dev/sdh2
Checking for bad blocks in read-write mode
From block 0 to 52428799
Testing with random pattern: done
Reading and comparing: done
Pass completed, 0 bad blocks found. (0/0/0 errors)
[root@vicky ~]#
Encrypt the root filesystem
Benchmark
I booted the RPI4 from a sdcard to verify the encryption speed by executing the cryptsetup benchmark
.
[root@minerva ~]# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 398395 iterations per second for 256-bit key
PBKDF2-sha256 641723 iterations per second for 256-bit key
PBKDF2-sha512 501231 iterations per second for 256-bit key
PBKDF2-ripemd160 330156 iterations per second for 256-bit key
PBKDF2-whirlpool 124356 iterations per second for 256-bit key
argon2i 4 iterations, 319214 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id 4 iterations, 321984 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 23.8 MiB/s 77.7 MiB/s
serpent-cbc 128b N/A N/A
twofish-cbc 128b 55.8 MiB/s 56.2 MiB/s
aes-cbc 256b 17.4 MiB/s 58.9 MiB/s
serpent-cbc 256b N/A N/A
twofish-cbc 256b 55.8 MiB/s 56.1 MiB/s
aes-xts 256b 85.0 MiB/s 74.9 MiB/s
serpent-xts 256b N/A N/A
twofish-xts 256b 61.1 MiB/s 60.4 MiB/s
aes-xts 512b 65.4 MiB/s 57.4 MiB/s
serpent-xts 512b N/A N/A
twofish-xts 512b 61.3 MiB/s 60.3 MiB/s
[root@minerva ~]#
Create the Luks volume
The aes-xts cipher seems to have the best performance on the RPI4.
[root@vicky ~]# cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha256 --use-random /dev/sdh2
WARNING!
========
This will overwrite data on /dev/sdh2 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sdh2:
Verify passphrase:
WARNING: Locking directory /run/cryptsetup is missing!
[root@vicky ~]#
Open the Luks volume
[root@vicky ~]# cryptsetup luksOpen /dev/sdh2 cryptroot
Enter passphrase for /dev/sdh2:
[root@vicky ~]#
Create the root filesystem
[root@vicky ~]# mkfs.ext4 /dev/mapper/cryptroot
mke2fs 1.45.6 (20-Mar-2020)
Creating filesystem with 13103104 4k blocks and 3276800 inodes
Filesystem UUID: 557677f1-9705-4beb-8c8b-e36c552730f3
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424
Allocating group tables: done
Writing inode tables: done
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done
[root@vicky ~]#
Mount and extract
Mount the root filesystem.
[root@vicky ~]# mount /dev/mapper/cryptroot /mnt/chroot
[root@vicky ~]# mkdir -p /mnt/chroot/boot
[root@vicky ~]# mount /dev/sdh1 /mnt/chroot/boot
[root@vicky ~]#
And extract the tarball.
[root@vicky manjaro]# cd /home/staf/Downloads/isos/manjaro/
[root@vicky manjaro]# tar xzvf Manjaro-ARM-xfce-rpi4-20.06.tgz -C /mnt/chroot/
[root@vicky manjaro]# sync
chroot
To continue the setup we need to boot or chroot into the operating system. It possible to run ARM64 code on a x86_64 system with qemu - qemu will emulate an arm64 CPU -.
Install qemu-arm-static
Install the qemu-arm package. It not in the main Archlinux distribution but it’s available as a AUR.
[staf@vicky ~]$ yay -S qemu-arm-static
copy qemu-arm-static
Copy the qemu-arm-static
into the chroot.
[root@vicky manjaro]# cp /usr/bin/qemu-arm-static /mnt/chroot/usr/bin/
[root@vicky manjaro]#
mount proc & co
To be able to run programs in the chroot we need the proc
, sys
and dev
filesystems mapped into the chroot.
[root@vicky ~]# mount -t proc none /mnt/chroot/proc
[root@vicky ~]# mount -t sysfs none /mnt/chroot/sys
[root@vicky ~]# mount -o bind /dev /mnt/chroot/dev
[root@vicky ~]# mount -o bind /dev/pts /mnt/chroot/dev/pts
[root@vicky ~]#
chroot
Chroot into ARM64 installation.
LANG=C chroot /mnt/chroot/
Set the PATH.
[root@vicky /]# export PATH=/sbin:/bin:/usr/sbin:/usr/bin
And verify that we are running aarch64.
[root@vicky /]# uname -a
Linux vicky 5.6.19.a-1-hardened #1 SMP PREEMPT Sat, 20 Jun 2020 15:16:50 +0000 aarch64 GNU/Linux
[root@vicky /]#
Update and install vi
Update all packages to the latest version.
[root@vicky /]# pacman -Syu
We need an editor.
root@vicky /]# pacman -S vi
resolving dependencies...
looking for conflicting packages...
Packages (1) vi-1:070224-4
Total Download Size: 0.15 MiB
Total Installed Size: 0.37 MiB
:: Proceed with installation? [Y/n] y
:: Retrieving packages...
vi-1:070224-4-aarch64 157.4 KiB 2.56 MiB/s 00:00 [##########################################] 100%
(1/1) checking keys in keyring [##########################################] 100%
(1/1) checking package integrity [##########################################] 100%
(1/1) loading package files [##########################################] 100%
(1/1) checking for file conflicts [##########################################] 100%
(1/1) checking available disk space [##########################################] 100%
:: Processing package changes...
(1/1) installing vi [##########################################] 100%
Optional dependencies for vi
s-nail: used by the preserve command for notification
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...
[root@vicky /]#
mkinitcpio
HOOKS
Add encrypt
to HOOKS
before filesystems
in /etc/mkinitcpio.conf
.
[root@vicky /]# vi /etc/mkinitcpio.conf
HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard fsck)
Create the boot image
[root@vicky /]# ls -l /etc/mkinitcpio.d/
total 4
-rw-r--r-- 1 root root 246 Jun 11 11:06 linux-rpi4.preset
[root@vicky /]#
[root@vicky /]# mkinitcpio -p linux-rpi4
==> Building image from preset: /etc/mkinitcpio.d/linux-rpi4.preset: 'default'
-> -k 4.19.127-1-MANJARO-ARM -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 4.19.127-1-MANJARO-ARM
-> Running build hook: [base]
-> Running build hook: [udev]
-> Running build hook: [autodetect]
-> Running build hook: [modconf]
-> Running build hook: [block]
-> Running build hook: [encrypt]
==> ERROR: module not found: `dm_integrity'
-> Running build hook: [filesystems]
-> Running build hook: [keyboard]
-> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> WARNING: errors were encountered during the build. The image may not be complete.
[root@vicky /]#
update boot settings…
Get the UUID for the boot and the root partition.
[root@vicky boot]# ls -l /dev/disk/by-uuid/ | grep -i sdh
lrwxrwxrwx 1 root root 12 Jul 8 11:42 xxxx-xxxx -> ../../sdh1
lrwxrwxrwx 1 root root 12 Jul 8 12:44 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> ../../sdh2
[root@vicky boot]#
The Raspberry PI uses cmdline.txt
to specify the boot options.
[root@vicky ~]# cd /boot
[root@vicky boot]#
[root@vicky boot]# cp cmdline.txt cmdline.txt_org
[root@vicky boot]#
cryptdevice=/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1:cryptroot root=/dev/mapper/cryptroot rw rootwait console=ttyAMA0,115200 console=t
ty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop snd-bcm2835.enable_compat
_alsa=0
fstab
[root@vicky etc]# cp fstab fstab_org
[root@vicky etc]# vi fstab
[root@vicky etc]#
# Static information about the filesystems.
# See fstab(5) for details.
# <file system> <dir> <type> <options> <dump> <pass>
UUID=xxxx-xxxx /boot vfat defaults 0 0
Finish your setup
Set the root password.
[root@vicky etc]# passwd
Set the timezone.
[root@vicky etc]# ln -s /usr/share/zoneinfo/Europe/Brussels /etc/localtime
Generate the required locales.
[root@vicky etc]# vi /etc/locale.gen
[root@vicky etc]# locale-gen
Set the hostname.
[root@vicky etc]# vi /etc/hostname
clean up
Exit chroot
[root@vicky etc]# exit
exit
[root@vicky ~]# uname -a
Linux vicky 5.6.19.a-1-hardened #1 SMP PREEMPT Sat, 20 Jun 2020 15:16:50 +0000 x86_64 GNU/Linux
[root@vicky ~]#
Make sure that there are no processes still running from the chroot.
[root@vicky ~]# ps aux | grep -i qemu
root 160666 0.0 0.1 323228 35468 ? Ssl 16:50 0:00 /usr/bin/qemu-aarch64-static /usr/bin/gpg-agent --homedir /etc/pacman.d/gnupg --use-standard-socket --daemon
root 203274 0.0 0.0 6812 2188 pts/1 S+ 17:14 0:00 grep -i qemu
[root@vicky ~]#
Kill the processes from the chroot.
[root@vicky ~]# kill 160666
[root@vicky ~]#
Umount the chroot filesystems.
[root@vicky manjaro]# mount | grep -i chroot | awk '{print $3}'
/mnt/chroot
/mnt/chroot/boot
/mnt/chroot/proc
/mnt/chroot/sys
/mnt/chroot/dev
/mnt/chroot/dev/pts
[root@vicky manjaro]#
[root@vicky manjaro]# mount | grep -i chroot | awk '{print $3}' | xargs -n1 umount
umount: /mnt/chroot: target is busy.
umount: /mnt/chroot/dev: target is busy.
[root@vicky manjaro]# mount | grep -i chroot | awk '{print $3}' | xargs -n1 umount
umount: /mnt/chroot: target is busy.
[root@vicky manjaro]# mount | grep -i chroot | awk '{print $3}' | xargs -n1 umount
[root@vicky manjaro]#
Close the luks volume…
[root@vicky ~]# cryptsetup luksClose cryptroot
[root@vicky ~]# sync
[root@vicky ~]#
Boot
Connect the usb disk to the raspberry pi and power it on. If you are lucky the PI will boot from the USB device and ask you to type the password to decrypt the root filesystem.
Have fun!
Leave a comment