We're gonna install Arch Linux with a RAID1 on two 3TB harddisks and an encrypted LVM.

About this tutorial

WARNING: This tutorial was first published in January 2013. Some or a lot of information here could and will be outdated! Please refer to the Arch Wiki for up-to-date information.

This tutorial is based on this one from Jason Ryan.

The original guide from February 2012 still uses initscripts and there are a lot of other parts that I wanted to update / modify (e.g. there is no Arch Installer Framework anymore), so it better fits me and takes systemd into account. Further I used 3TB harddisks which needs some special treatment and I wanted to include some more information about basic installation, the original tutorial doesn't contain.

Preparing a bootable live-stick

Download the latest installation-media from https://www.archlinux.org/download/

NOTE: Check with lsblk that the USB device is not mounted, and use /dev/sdx instead of /dev/sdx1.

# dd bs=4M if=/path/to/archlinux.iso of=/dev/sdX


How to restore the USB drive

Because the ISO image is a hybrid which can either be burned to a disc or directly written to a USB drive, it doesn't include a standard partition table.

After you install Arch Linux and you're done with the USB drive, you should zero out its first 512 bytes (meaning the boot code from the MBR and the non-standard partition table) if you want to restore it to full capacity:

# dd count=1 bs=512 if=/dev/zero of=/dev/sdx

Then create a new partition table (e.g. “msdos”) and filesystem (e.g. EXT4, FAT32) using gparted, or from a terminal:

For EXT2/3/4 (adjust accordingly), it would be:

# cfdisk /dev/sdx
# mkfs.ext4 /dev/sdx1
# e2label /dev/sdx1 USB_STICK

For FAT32, install the dosfstools package and run:

# cfdisk /dev/sdx
# mkfs.vfat -F32 /dev/sdx1
# dosfslabel /dev/sdx1 USB_STICK


Peparing the harddisks

Shred all the partitions you want to encrypt:

# shred -v -n 1 /dev/sda2
# shred -v -n 1 /dev/sdb2

NOTE: This will take a loooooooooooooooooong time!

Create the new partitions with parted. Because of our 3TB-disks, we need to create GPT-partition-tables. The partitions need to be identical on both disks. Otherwise we'll loose space on the raid.

Beware: If you want to use grub-bios, you'll need to create an empty 2MB partition at the beginning of the disk (only if it's a disk more than 2TB)!!! Please consider this during the further installation.

Create the raid1-devices

Now let's create the two raid1-devices:

# modprobe raid1 && modprobe dm-mod
# mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=0.90 /dev/sd[ab]1
# mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sd[ab]2

The metadata=0.90 is important if you want to use lilo (as I did) or grub-legacy. If you intend to use grub-bios, just remove it.

At this point, the raid1-devices are syncing. You can check the progress, if you switch to another TTY and enter:

# watch -n1 cat /proc/mdstat

NOTE: This took in my case ~6 hours!

Check if everything went fine:

# mdadm --misc --detail /dev/md[01] | less

If everything went fine, you can switch TTYs again

Encrypt the raid1-device

Let's encrypt the second raid1-device (/dev/md1):

# modprobe dm-crypt
# cryptsetup --cipher=aes-xts-plain --verify-passphrase --key-size=512 luksFormat /dev/md1

Now we can open the encrypted device, in order to create the logical volumes:

# cryptsetup luksOpen /dev/md1 cryptdisk1

If you had to reboot after the creation of the raid1, I had some issues to reactivate the arrays. Somehow they were detected automatically as /dev/md126 and /dev/md127. This happens, because it doesn't find an /etc/mdadm.conf file, which we will create later.

Run following commands before the cryptsetup-command and you should be fine:

# modprobe raid1 && modprobe dm-mod
# mdadm --stop /dev/md*
# mdadm --assemble /dev/md0 /dev/sda1 /dev/sdb1
# mdadm --assemble /dev/md1 /dev/sda2 /dev/sdb2

Create the LVM

The three next steps create, in this order, the physical volume (the container, if you will), the group and then the individual volumes contained in the group. Choose simple, memorable names and do not hypenate them. The {pv,vg,lv}display commands print out the details of the devices once created.

# pvcreate /dev/mapper/cryptdisk
# pvdisplay

# vgcreate vgroup /dev/mapper/cryptdisk
# vgdisplay

# lvcreate --size 150G --name lvroot vgroup
# lvcreate --contiguous y --size 3G --name lvswap vgroup
# lvcreate --size 500G --name lvhome vgroup
# lvcreate --extents +100%FREE --name lvvar vgroup
# lvdisplay

Installing Arch-Linux

Now we start the normal Arch-installation.

NOTE: To get the most actual informations about installing Arch Linux, check out the Installation Guide in the Arch Wiki!

Change the keyboard-layout:

# loadkeys de_CH-latin1

Or whatever keyboard-layout you use.

If you had to reboot after the creation of the raid1, I had some issues to reactivate the arrays. Somehow they were detected automatically as /dev/md126 and /dev/md127. This happens, because it doesn't find an /etc/mdadm.conf file, which we will create later.

Run following commands and you should be fine:

# modprobe raid1 && modprobe dm-mod
# mdadm --stop /dev/md*
# mdadm --assemble /dev/md0 /dev/sda1 /dev/sdb1
# mdadm --assemble /dev/md1 /dev/sda2 /dev/sdb2
# cryptsetup luksOpen /dev/md1 cryptdisk1
# vgchange -ay

Now we can mount the partitions under /mnt/:

# mount /dev/vgroup/lvroot /mnt/
# mount /dev/vgroup/lvvar /mnt/var/
# mount /dev/vgroup/lvhome /mnt/home/
# mount /dev/md0 /mnt/boot/

Now we need an internet-connection. If you're connected via LAN, it should automatically establish a connection. If not, usually it's enough to just run:

# dhcpd

Edit /etc/pacman.d/mirrorlist. Put your preferred mirror on top of the list. A copy of this file will be created in your new system.

Install the base-system

Now we can install the base-system into /mnt/:

# pacstrap /mnt base base-devel

You can include other packages. Just put them (space seperated) on the end of the above command. e.g. the bootloader.

Generate the /etc/mdadm.conf

Switch to another TTY and update your Raid configuration prior to configuring your system. This means that when your initrd is regenerated, it will inlcude the correct Raid information:

# mdadm --examine --scan > /mnt/etc/mdadm.conf

Generate the /etc/fstab

Now we can generate the /etc/fstab:

# genfstab -p /mnt >> /mnt/etc/fstab


Next step is to chroot into our new system:

# arch-chroot /mnt


Set hostname

Write your hostname to /etc/hostname or

# hostnamectl set-hostname myhostname

Set the default locale

The default system locale is configured in /etc/locale.conf. To set the default locale, do:

# localectl set-locale LANG="de_DE.utf8"

NOTE: Before you set the default locale, you first need to enable locales available to the system by uncommenting them in /etc/locale.gen and then executing locale-gen as root. The locale set via localectl must be one of the uncommented locales in /etc/locale.gen`.

See man 1 localectl and man 5 locale.conf for details.

Here is an example file:


Configure the virtual console

The virtual console (keyboard mapping, console font and console map) is configured in /etc/vconsole.conf:


NOTE: As of systemd-194, the built-in kernel font and the us keymap are used if KEYMAP= and FONT= are empty or not set.

Another way to set the keyboard mapping (keymap) is doing:

# localectl set-keymap de

localectl can also be used to set the X11 keymap:

# localectl set-x11-keymap de

See man 1 localectl and man 5 vconsole.conf for details.

Set the time zone

The time zone is configured by creating an appropriate /etc/localtime symlink, pointing to a zoneinfo file under /usr/share/zoneinfo/. To do this automatically:

# timedatectl set-timezone America/Toronto

See man 1 timedatectl, man 5 localtime, and man 7 archlinux for more details.

Alternatively, create the symlink yourself:

# ln -sf ../usr/share/zoneinfo/America/Toronto /etc/localtime

If the old configuration file /etc/timezone exists you can now remove it safely, because it is not used by systemd.

Enable services

Now we have to enable all services we like to start at every boot:

# systemctl enable cronie.service
# systemctl enable dhcpcd@YOURINTERFACE.service (e.g. dhcpcd@eth0.service)
# systemctl enable lvm.service
# systemctl enable lvm-on-crypt.service

Here you'll find a list with all daemons.



Now we edit /etc/mkinitcpio.conf:

Important are:

MODULES="... dm_mod dm_crypt aes_x86_64 raid1 ..."
HOOKS="... base udev mdadm_udev encrypt lvm2 filesystems ..."

NOTE: The right order in the HOOKS-line is VERY IMPORTANT to be able to boot the system!

Mine looks like this:

# vim:set ft=sh
# The following modules are loaded before any boot hooks are
# run.  Advanced users may wish to specify all system modules
# in this array.  For instance:
#     MODULES="piix ide_disk reiserfs"
MODULES="dm_mod dm_crypt aes_x86_64 raid1"

# This setting includes any additional binaries a given user may
# wish into the CPIO image.  This is run last, so it may be used to
# override the actual binaries included by a given hook
# BINARIES are dependency parsed, so you may safely ignore libraries

# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in any way.  This is useful for config files.
# Some users may wish to include modprobe.conf for custom module options
# like so:
#    FILES="/etc/modprobe.d/modprobe.conf"

# This is the most important setting in this file.  The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
##   This setup specifies all modules in the MODULES setting above.
##   No raid, lvm2, or encrypted root is needed.
#    HOOKS="base"
##   This setup will autodetect all modules for your system and should
##   work as a sane default
#    HOOKS="base udev autodetect pata scsi sata filesystems"
##   This is identical to the above, except the old ide subsystem is
##   used for IDE devices instead of the new pata subsystem.
#    HOOKS="base udev autodetect ide scsi sata filesystems"
##   This setup will generate a 'full' image which supports most systems.
##   No autodetection is done.
#    HOOKS="base udev pata scsi sata usb filesystems"
##   This setup assembles a pata mdadm array with an encrypted root FS.
##   Note: See 'mkinitcpio -H mdadm' for more information on raid devices.
#    HOOKS="base udev pata mdadm encrypt filesystems"
##   This setup loads an lvm2 volume group on a usb device.
#    HOOKS="base udev usb lvm2 filesystems"
##   NOTE: If you have /usr on a separate partition, you MUST include the
#    usr, fsck and shutdown hooks.
HOOKS="base udev block usbinput mdadm_udev encrypt lvm2 filesystems fsck"

# Use this to compress the initramfs image. By default, gzip compression
# is used. Use 'cat' to create an uncompressed image.

# Additional options for the compressor

Create the initial RAM disk with:

# mkinitcpio -p linux

Installing and configuring the Lilo boot loader

First install Lilo with

# pacman -S lilo

Now we modify /etc/lilo.conf.

Mine looks like this:

# /etc/lilo.conf

# This line often fixes L40 errors on bootup
# disk=/dev/hda bios=0x80


        # root=/dev/md1
        append="root=/dev/mapper/vgroup-lvroot cryptdevice=/dev/md1:vgroup init=/usr/lib/systemd/systemd"

        append="root=/dev/mapper/vgroup-lvroot cryptdevice=/dev/md1:vgroup init=/usr/lib/systemd/systemd"

#       label=dos

To apply the new configuration run:

# lilo

As a reminder, consider that LILO needs to be run after every kernel upgrade, otherwise the system is likely to be left in an unbootable state.

Finish the installation

Set a root-password, running:

# passwd

Exit the chroot environment:

# exit

Unmount everything from /mnt/:

# umount /mnt/{boot,home,var,}

Hooray!!! That should be it!

Restart your new system with:

# reboot

Edit /etc/pacman.conf and configure pacman's options, also enabling the repositories you need (e.g. multilib if you've chosen x86_64).

Update your system:

# pacman -Syu

Adding the swap to '/etc/fstab'

I had to add the swap manually to the /etc/fstab.

Mine looks like this:

# /etc/fstab: static file system information
# <file system> <dir>   <type>  <options>   <dump>  <pass>
tmpfs       /tmp    tmpfs   nodev,nosuid    0   0
# UUID=50921c5c-ffac-495f-a344-30e2eb0208e5
/dev/mapper/vgroup-lvroot   /           ext4        rw,relatime 0 1

# UUID=43fb1bf5-23c3-4373-a23f-d47064593931
/dev/mapper/vgroup-lvhome   /home       ext4        rw,relatime 0 2

# UUID=8fa50331-d40f-4550-97c3-87ab6a469905
/dev/md0                /boot       ext4        rw,relatime,stripe=4    0 2

# UUID=e23a9ad4-3ad8-4059-85bc-fd66d0bc5062
/dev/mapper/vgroup-lvvar    /var        ext4        rw,relatime 0 2

/dev/mapper/vgroup-lvswap   none        swap        sw      0 0



# pacman -S sudo

Then edit /etc/sudoers:

Example: I uncommented the line

%wheel ALL=(ALL) ALL

In this scenario, everyone in the group wheel is able to execute commands with sudo, but they have to enter their passphrase.

More about that


To enable tab-completion with sudo, install the bash-completion package from the official repositories. See tab-completion for more information.

# pacman -S bash-completion

Alternatively, add the following to your ~/.bashrc:

complete -cf sudo


arch linux  linux