Français [English]

Alpine Linux Installation Guide with Disk Encryption (except boot), Btrfs, rEFInd

Follow this guide at your own risk!. This post was first written on November 28, 2024 and was updated on January 2025.

Installation Image

We suppose that the reader uses Linux to install the Alpine image on an external drive.

Get the image on official website. In most cases, the image you want is the “standard” x86_64 one. Also download the sha256 signature next to the green button, and download the GPG signature. Finally, retrieve the GPG key on the top of the page. Click on the hexadecimals to download it. At the end you should have (the version number might be different):

File What it’s for
alpine-standard-3.20.3-x86_64.iso Installation image
alpine-standard-3.20.3-x86_64.iso.asc GPG signature
alpine-standard-3.20.3-x86_64.iso.sha256 sha256 signature
ncopa.asc Alpine Linux developper GPG public key

Check the different elements 1:

gpg --import ncopa.asc
gpg --fingerprint ncopa@alpinelinux.org  # Check that the fingerprint is the same as the one on the Alpine Linux webpage

# Check the GPG signature of the image
gpg --verify alpine-standard-3.20.3-x86_64.iso.asc alpine-standard-3.20.3-x86_64.iso

# Check the sha256 signature
sha256sum -c alpine-standard-3.20.3-x86_64.iso.sha256

Example of correct GPG verification (some lines have been removed):

gpg: Good signature from "Natanael Copa <ncopa@alpinelinux.org>" [unknown]

And for sha256sum :

alpine-standard-3.20.3-x86_64.iso: OK

Flash the image on a USB stick. Everything on it will be erased.

lsblk  # Identify the USB stick
umount /dev/sdX  # Should show: umount: /dev/sdX: not mounted

cat alpine-standard-3.20.3-x86_64.iso > /dev/sdX
sync

Alpine Linux Installation

Boot the USB key. Log in with root (without password).

System Configuration

setup-keymap  # Especially useful for non-QWERTY keyboards
setup-hostname
setup-interfaces  # For Internet connectivity
rc-service networking start

If you have set a static configuration for your Internet connection, also run setup-dns 2.

For Wi-Fi, also run rc-update add wpa_supplicant boot.

Continue with:

passwd  # `root` password
setup-timezone
rc-update add networking boot
rc-update add seedrng boot
rc-update add acpid default
rc-service acpid start

Change as below /etc/hosts with vi. If your system is under a specific domain, change <domain> accordingly. If not the case or if you don’t know what this is about, write localdomain for <domain>.

127.0.0.1       <hostname> <hostname>.<domain> localhost localhost.localdomain
::1             <hostname> <hostname>.<domain> localhost localhost.localdomain

If you don’t know how to use vi, type i, write your text and save and quit with echap, ZZ.

Then:

setup-ntp  # `chrony` is a good choice
setup-apkrepos

Change the file /etc/apk/repositories with vi, switch the http with https on the line http://dl-cdn.alpinelinux.org/alpine/v3.20/main (the domain name might be different depending on how you set up setup-apkrepos) and add the two following lines 3 4:

https://dl-cdn.alpinelinux.org/alpine/v3.20/community
@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing

Finally run:

apk update  # Check the later configuration works. Otherwise double check `/etc/apk/repositories`
setup-sshd  # Not necessary if you don't want your system to be accessible through SSH (e.g. for laptops)
apk add cryptsetup btrfs-progs dosfstools parted mkinitfs refind@testing
modprobe btrfs

Partitioning

Replace /dev/sdX with the disk you want to install Alpine Linux on. To identify it, install with apk the tool lsblk.

parted -a optimal /dev/sdX
(parted) mklabel gpt
(parted) mkpart primary fat32 0% 1G
(parted) name 1 boot
(parted) set 1 boot on
(parted) mkpart primary btrfs 1G 100%
(parted) name 2 crypto-luks

Filesystem and Encryption

mkfs.vfat -F32 /dev/sdX1
cryptsetup luksFormat /dev/sdX2  # Choose a password
cryptsetup open /dev/sdX2 cryptroot
mkfs.btrfs /dev/mapper/cryptroot

mount /dev/mapper/cryptroot /mnt
btrfs subvol create /mnt/@
btrfs subvol create /mnt/@home
btrfs subvol create /mnt/@snapshots
btrfs subvol create /mnt/@var_log
btrfs subvol create /mnt/@swap
umount /mnt

mount -o defaults,subvol=@ /dev/mapper/cryptroot /mnt
mkdir -p /mnt/boot && mount -t vfat /dev/sdX1 /mnt/boot
mkdir -p /mnt/home && mount -o defaults,subvol=@home /dev/mapper/cryptroot /mnt/home
mkdir -p /mnt/.snapshots && mount -o defaults,subvol=@snapshots /dev/mapper/cryptroot /mnt/.snapshots
mkdir -p /mnt/var/log && mount -o defaults,subvol=@var_log /dev/mapper/cryptroot /mnt/var/log
mkdir -p /mnt/swap && mount -o defaults,subvol=@swap /dev/mapper/cryptroot /mnt/swap

Generate a swap file of size 3/2 of your available RAM (if you have between 8 and 64GB)5. For instance with 8GB of RAM 6:

btrfs filesystem mkswapfile --size 12G --uuid clear /mnt/swap/swapfile
swapon /mnt/swap/swapfile
rc-update add swap

Base System Installation

BOOTLOADER=none setup-disk -m sys /mnt/

Post-installation Configuration

fstab File

Check it was correctly generated:

cat /mnt/etc/fstab

There’s probably a missing line for swap. Add it with 7:

echo "/swap/swapfile none swap defaults 0 0" >> /mnt/etc/fstab

mkinitfs Configuration

Add the following line 6:

echo btrfs >> /mnt/etc/modules

Edit the file /mnt/etc/mkinitfs/mkinitfs.conf and add the following modules

features="... cryptsetup kms keymap resume"

Add other modules you might also need like nvme. The rebuild the initial RAM disk:

mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls /mnt/lib/modules/)

rEFInd

Install rEFInd with:

refind-install --root /mnt/
mkdir /mnt/boot/EFI/BOOT/  # Fallback
cp /mnt/boot/EFI/refind/refind_x64.efi /mnt/boot/EFI/BOOT/bootx64.efi

Finally, change the rEFInd configuration:

CRYPT_UUID=$(blkid /dev/sdX2 | sed -n 's/.*UUID="\([^"]*\)".*/\1/p')
ROOT_UUID=$(blkid /dev/mapper/cryptroot | sed -n 's/.*UUID="\([^"]*\)".*/\1/p')
SWAP_OFFSET=$(btrfs inspect-internal map-swapfile -r /mnt/swap/swapfile)

echo "\"Boot with default options\" \"cryptroot=UUID=$CRYPT_UUID cryptdm=luks-$CRYPT_UUID root=UUID=$ROOT_UUID rootfstype=btrfs rootflags=subvol=@ resume=UUID=$ROOT_UUID resume_offset=$SWAP_OFFSET quiet\"" > /mnt/boot/refind_linux.conf
echo "\"Boot with verbose output\" \"cryptroot=UUID=$CRYPT_UUID cryptdm=luks-$CRYPT_UUID root=UUID=$ROOT_UUID rootfstype=btrfs rootflags=subvol=@ resume=UUID=$ROOT_UUID resume_offset=$SWAP_OFFSET\"" >> /mnt/boot/refind_linux.conf

Check everything went well:

cat /mnt/boot/refind_linux.conf

Finally:

swapoff /mnt/swap/swapfile
umount /mnt/boot
umount /dev/mapper/cryptroot  # Repeat until you can't unmount
cryptsetup close /dev/mapper/cryptroot
reboot

You are done!

Stepping Stones to a Wayland Compositor

Add an administrator account 8:

adduser pialwis
adduser pialwis wheel  # Adds `pialwis` to the `wheel` group
apk add doas  # Alternative to `sudo`
vi /etc/doas.conf  # Uncomment the line with `wheel`

Check doas works: logout from root (with exit or C-D), login with the created account, and execute doas whoami (it should show root). If and only if it worked, you can lock the root account with passwd -l root.

The home directory of the created account is by default readable by everyone. Change this with chmod o-rx /home/pialwis.

To install sway, you can use the convenient setup-desktop 9. For another Wayland compositor, run:

setup-wayland-base util-linux-login
apk add river river-doc  # Example with river
apk add foot font-noto  # And other useful packages (firefox, libreoffice...)
# And other configurations for your given compositor

  1. https://wiki.alpinelinux.org/wiki/Installation#Verifying_downloaded_image ↩︎

  2. https://wiki.alpinelinux.org/wiki/LVM_on_LUKS#Preparing_the_Temporary_Installation_Environment ↩︎

  3. https://wiki.alpinelinux.org/wiki/Bootloaders#rEFInd ↩︎

  4. https://wiki.alpinelinux.org/wiki/Repositories#Using_testing_repository ↩︎

  5.  ↩︎
  6. https://wiki.alpinelinux.org/wiki/Filesystems#Swap_Partition ↩︎ ↩︎

  7. https://wiki.alpinelinux.org/wiki/LVM_on_LUKS#Installing_Alpine_Linux ↩︎

  8. https://wiki.alpinelinux.org/wiki/Setting_up_a_new_user ↩︎

  9. https://wiki.alpinelinux.org/wiki/Sway#Installation_using_setup-desktop ↩︎

* Next >