7 min | linux
Encrypted Void Linux musl install via CLI
Looking for a lightweight linux distribution, not yet infected by systemd, that tries hard to follow the BSD philosophy?
This is my step by step guide, that I’ve built over time and I constantly keep up to date, to install a minimal version of void linux via cli.
A few assumptions to make the process easier, we are going to:
- Boot from uefi
- Disable secure boot
- Not encrypt the boot partition
- Use a single partition (no root/home separation)
- Use a swap file instead of a partition
If reading the above makes you concerned about security threats such as the evil maid attack you should definitely go for full disk encryption with detached headers, so this is clearly not the guide for you.
Before we get started head over to the void linux download page and get hold of the x64 musl iso image. With the iso downloaded we can write it to a usb stick using the dd command on linux or mac (if you are on windows you can use a tool like unetbootin).
# make sure to replace sdX with the correct # device as dd is not a forgiving command # you can use the lsblk command to find it sudo dd bs=4M if=void-live-x86_64-musl-20191109.iso of=/dev/sdX
Now make sure your bios is set to use uefi and boot your machine from the usb drive you just created. You should be greeted by a login screen where you can enter root as the username and voidlinux as the password to get in.
This is the void linux live environment (running entirely from ram) from which we will perform the installation.
We can start by jumping into bash (as the live image uses the sh shell) and setting the keyboard layout.
bash loadkeys uk
If you are planning to use wifi, connect using the wpa supplicant and then get a lease via the dhcp client.
# replace the interface ssid and psw wpa_supplicant -B -i wlp4s0 -c <(wpa_passphrase ssid psw) dhcpcd wlp4s0
If you are on a wired connection, find your ethernet interface and use the dhcp client to obtain a lease.
Time to check our connection by issuing the ping command.
ping -c 3 126.96.36.199
We are now ready to wipe the internal disk and create the new partitions on a gpt schema.
# replace nvme0n1 with your internal disk device # we discard the ssd content first blkdiscard /dev/nvme0n1 # then use fdisk to partition fdisk /dev/nvme0n1 # create a blank gpt schema g # create the boot partition n # default the first sector # enter the size of the last sector +200m # change partition type t # set it to efi 1 # create another partition (we will encrypt this later on) n # default everything # write the changes to disk w
Time to create our encrypted luks container on the second partition, this will hold our rootfs.
# replace nvme0n1p2 with your second partition cryptsetup \ --cipher aes-xts-plain64 \ --key-size 512 \ --hash sha512 \ --iter-time 5000 \ --use-random \ luksFormat /dev/nvme0n1p2
We should now decrypt our luks container to prep its inside.
# replace nvme0n1p2 with your second partition cryptsetup luksOpen /dev/nvme0n1p2 crypto
Time to create the filesystems, we are going to use FAT32 for the boot partition (as it’s required by the uefi boot) and btrfs on top of the luks container.
# replace nvme0n1p1 with your boot partition mkfs.fat -F 32 /dev/nvme0n1p1 mkfs.btrfs -L rootfs /dev/mapper/crypto
The disk is now ready, we shoud mount the volumes and do some cleanup.
mount /dev/mapper/crypto /mnt mkdir /mnt/boot # replace nvme0n1p1 with your boot partition mount /dev/nvme0n1p1 /mnt/boot
As we are installing the musl variant of void linux we will need to export an environmental variable to tip the package manager (xbps) of the intended architecture.
We can now install the base system and few additional packages, grub (the bootloader) and cryptsetup (to manage the encrypted volume).
xbps-install -Sy \ --repository=https://alpha.de.repo.voidlinux.org/current/musl \ --rootdir /mnt \ base-system \ cryptsetup \ grub-x86_64-efi
One last step, before we enter our newly installed system, is to mount some folders from the host that will be used by grub later on.
mount -t proc /proc /mnt/proc mount --rbind /dev /mnt/dev mount --rbind /sys /mnt/sys
We can now chroot into the new installation and change both the default shell and root password.
chroot /mnt /bin/bash # change the default shell to bash chsh -s /bin/bash # change the root password passwd
Instead of using a swap partition we are going to take advantage of a swap file, this way we can resize and relocate it however we see fit. As we are using btrfs we need to disable cow (copy on write) and compression before we can enable swap using the swapfile.
# create a zero length file truncate -s 0 /swapfile # disable cow chattr +C /swapfile # disable compression btrfs property set /swapfile compression none # allocate the size fallocate -l 24g /swapfile # lock down permissions chmod 600 /swapfile # make it swappable mkswap /swapfile
Time to create a new user and assign it to some of the groups, feel free to add or remove groups here depending on your requirements. Just note that the wheel group is used in the last step to allow sudo access to our newly created user.
# replace zerocool with your user handle useradd \ --create-home \ --groups wheel,users,audio,video,storage,cdrom,input \ --shell /bin/bash \ zerocool # change the password passwd zerocool # fire the visudo command # and uncomment the following line # to allow sudo access to # users in the wheel group %wheel ALL=(ALL) ALL
Now we can set some defaults to handle the timezone and keymap at boot. We should also set the correct language for our locale.
# tweak the following lines in /etc/rc.conf HARDWARECLOCK="UTC" TIMEZONE="Europe/London" KEYMAP="uk" # tweak the language for your locale in /etc/locale.conf LANG=en_GB.UTF-8
We need to set the hostname in two places.
# add the hostname to /etc/hostname # replace gibson with your hostname echo gibson > /etc/hostname # tweak the /etc/hosts to include your hostname # also replace gibson here with your hostname 127.0.0.1 gibson.lan gibson localhost.localdomain localhost ::1 gibson.lan gibson localhost.localdomain localhost ip6-localhost
Our next step is to populate the fstab with the boot volume and the swap file.
# add the following lines to your /etc/fstab # replace nvme0n1p1 with your boot partition /dev/nvme0n1p1 /boot vfat rw,noatime,discard 0 2 /swapfile none swap defaults 0 0
As we are going to use dracut to generate the initramfs image to boostrap the kernel we need to add an override to install only what is needed to boot the localhost.
# create a new file in /etc/dracut.conf.d/override.conf # containing the following line hostonly=yes
Now we can tweak the grub default config to disable timeout and enable the autoassembly of special devices, in our case the luks volume, don’t forget to add the discard option if you are using an ssd.
# edit the following lines in /etc/default/grub GRUB_TIMEOUT=0 GRUB_CMDLINE_LINUX_DEFAULT="loglevel=4 rd.auto=1 rd.luks.allow-discards"
Time to install the bootloader.
# install grub grub-install \ --target=x86_64-efi \ --efi-directory=/boot # generate grub config grub-mkconfig -o /boot/grub/grub.cfg
Last step is to generate the initramfs image using dracut.
# replace 5.8 with the correct version # you can find it in the output # of the grub command above xbps-reconfigure -f linux5.8
All done, we are now ready to reboot into void linux.
# exit the chroot exit # unmount recursively from /mnt umount -R /mnt reboot
Now that our base install is complete we can go ahead and setup xorg and i3wm.