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
-
https://wiki.alpinelinux.org/wiki/Installation#Verifying_downloaded_image ↩︎
-
https://wiki.alpinelinux.org/wiki/LVM_on_LUKS#Preparing_the_Temporary_Installation_Environment ↩︎
-
https://wiki.alpinelinux.org/wiki/Repositories#Using_testing_repository ↩︎
- ↩︎
-
https://wiki.alpinelinux.org/wiki/Filesystems#Swap_Partition ↩︎ ↩︎
-
https://wiki.alpinelinux.org/wiki/LVM_on_LUKS#Installing_Alpine_Linux ↩︎
-
https://wiki.alpinelinux.org/wiki/Sway#Installation_using_setup-desktop ↩︎
* Next >