The Arch of Progress

My home laptop is a 5(?) year old Lenovo Yoga 13. I’ve been running Ubuntu 17.04 on it for the last year. Lately I noticed it was running out of memory on a regular basis and then having major problems. Basically just locking up all the time.

The machine only has 4Gb of RAM, and just getting the desktop environment up and running on Ubuntu was eating up about 1Gb. You throw in a web browser and Atom with all the plugins I run, and it was pretty easy to see why I was having problems.

So I decided it was time to try out Arch Linux again. I had tried it on a laptop maybe 10 years ago, and had reasonable success, and thought the whole idea was pretty cool. Build up your own operating system starting from a pretty bare minimum base. Not to mention their wiki is bar none the best reference when it comes to the intricacies Linux operating system internals.

The following are the steps I took in order to get Arch installed and running with what you would reasonably expect to have from an operating system. This is as much notes for my benefit as a guide for anyone else.

BIG NOTE: I performed nearly all these steps to install onto a thumb drive and booted into that to be certain that it would work out before I wiped my internal hard drive.

ALSO NOTE: Arch is a very much do it yourself kind of distribution. Do not expect everything to work right out of the box, and your hardware may require configurations different from mine.

Firstly, find a thumb drive, download the Arch installation iso from here, and make a bootable thumb drive with the following command.

dd bs=4M if=/path/to/archlinux.iso of=/dev/sdx status=progress oflag=sync

Note that sdx should be your thumb drive, and it should not be mounted. This will erase everything else from that drive, so be sure you got the right one (additional details can be found here).

Now restart your machine and get it to boot from the thumb drive. You may need to hold or press some button as your machine boots to get to a menu that allows you to select which device it boots from.

Once it’s booted, you’ll be dropped to a command prompt. The following is the list of commands and files I edited to get to a usable system. I’ll try and comment and explain everything as best I can, but the best source of information is the Arch Wiki starting with the installation guide.

First, make sure you are connected to the internet. If you have an ethernet jack plugged in, chances are pretty good you’ll be connected automatically. You can check with a simple ping command like ping My laptop is wifi only, so I had to do the following.

systemctl stop dhcpcd # stop the dhcp service
ip link # outputs the networking interfaces and their status
ip link set wlp0 up # where wlp0 is the name of your network interface
iw dev wlp0 scan | less # to find the name of a wifi network to connect to

The edit the file  /etc/wpa_supplicant/wpa_supplicant.conf (I use vim, but nano is available too) and add the following lines:


Then keep going with the following commands:

wpa_suplicant -B -i wlp0 -c /etc/wpa_supplicant/wpa_supplicant.conf
> scan
> add_network
> set_network 0 ssid "NetworkName"
> set_network 0 psk "thepassword"
> enable_network 0
> save_config
> exit # or Ctrl-d to exit wpa_cli
systemctl start dhcpcd # restart the dhcp service
timedatectl set-ntp true # sync time with remote server
timedatectl status

Once you restart the dhcp service it may take a few seconds for you to be connected to the internet, but you can again check with a ping command. Also, if your wireless network isn’t using WPA2 you may need to do something different. There’s also a chance that your wireless connection may need additional firmware or kernel modules not included in the installation environment. For more information see the this page on the Arch Wiki.

The following commands will get your hard drive set up with full disk encryption. If you don’t want that you can skip the encryption parts here, and when setting up the bootloader. Also, my laptop has UEFI, but if your machine doesn’t you made need to do something other than a GPT partition table. You can find lots more information the Arch Wiki, starting here.

I set up my disk with a GPT partition table, with the 1st partition having 550Mb and type EFI System, and the 2nd partition taking up the remaining space with type Linux System. This partition then gets encrypted. Then, using LVM I set up 8Gb of swap space inside the encrypted partition, with the remainder of the system taking up the rest of the space.

lsblk # list your available hard drives
fdisk /dev/sdx # partition the hard drive. make sure you get the right one
mkfs.fat -F32 /dev/sdxX # put FAT32 filesystem on the boot partition likely /dev/sda1
modprobe dm_crypt # make sure the encryption module is loaded
cryptsetup benchmark # reports speeds of different ciphers and key sizes
# Your best cipher and key size are potentially different
cryptsetup -v --cipher twofish-xts-plain64 --key-size 512 luksFormat /dev/sdxX # /dev/sda2 for me
cryptsetup open /dev/sdxX cryptlvm # mount the encrypted drive with name cryptlvm
pvcreate /dev/mapper/cryptlvm # create a physical volume for LVM
vgcreate VolumeGroup /dev/mapper/cryptlvm # Create logical volume group named VolumeGroup
lvcreate -L 8G VolumeGroup -n swap # create 8Gb of swap space
lvcreate -l 100%FREE VolumeGroup -n root # Use remaining space for system
mkfs.ext4 /dev/VolumeGroup/root # format drive with EXT4 file system
mkswap /dev/VolumeGroup/swap # make swap
mount /dev/VolumeGroup/root /mnt # Mount our filesystem on /mnt
swapon /dev/VolumeGroup/swap # Turn on swap space
mkdir /mnt/boot # make a place to mount our boot partition
mount /dev/sdxX /mnt/boot # mount the boot partition
vim /etc/pacman.d/mirrorlist # move closer/faster mirrors to the top

Now we’re finally ready to install the operating system on the hard drive. It’s done with the following command, listing all of the packages you want installed to start with. I’ve annotated it with why we want each package, but you need to omit the comments and put it all on one line. You can also install any you missed later using pacman.

pacstrap /mnt \ # Install system in /mnt
  base \ # A bare bones operating system
  base-devel \ # some compilers and tools
  grub \ # a bootloader
  efibootmgr \ # for uefi systems
  intel-ucode \ # microcode for intel chips
  networkmanager \ # for network configuration with a GUI
  network-manager-applet \ # applet in task bar for network manager
  wireless_tools \ # additional wireless tools
  hdparm \ # hard drive power management tools
  cups \ # for using printers
  system-config-printer \ # GUI for configuring printers
  cups-pk-helper \ # for allowing users to configure printers
  hplip \ # HP printer drivers
  nftables \ # firewall
  nss-mdns \ # needed for avahi stuff?
  avahi \ # for detecting network services like printers
  bluez \ # bluetooth support for network manager
  bluez-utils \ # additional bluetooth support
  xorg \ # X11 display server
  i3-wm \ # a lightweight tiling window manager
  i3status \ # an i3 status bar
  dmenu \ # a good app launcher for i3
  lightdm \ # graphical login manager
  lightdm-gtk-greeter \ # the login screen
  terminator \ # my favorite terminal emulator
  sudo \ # allow users to run administrative commands
  zsh \ # I like zsh instead of bash for my shell
  vim \ # My favorite command line text editor
  git \ # version control
  elinks \ # a terminal web browser
  wget \ # for downloading files via command line
  volumeicon \ # for volume control
  atom \ # my favorite text/code editor
  nautilus \ # file browser
  ttf-hack \ # good monospaced font
  openssh \ # for connecting to other machines

I probably missed one or two that I ended up with in the end, but this should get you most of the way there. Then generate an fstab with genfstab -U /mnt > /mnt/etc/fstab and chroot into the system for some final setup with arch-chroot /mnt.

Set up time-zone, language and computer name settings as follows.

ln -sf /usr/share/zoneinfo/Region/City /etc/localtime # replacing Region and City
hwclock --systohc
vim /etc/locale.gen # uncomment the line en_US.UTF-8 UTF-8
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "yourcomputername" > /etc/hostname

Add the following to /etc/hosts localhost
::1 localhost yourcomputername.localdomain yourcomputername

Now configure the bootloader. If you don’t do this you won’t be able to boot the system.

Edit /etc/mkinitcpio.conf to have the following line.

HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 resume filesystems fsck)

Then run mkinitcpio -p linux to create the initial boot kernel.

Now edit /etc/default/grub to have the following lines, where device-uuid is the uuid of the disk partition you encrypted, which you can find with the command blkid.  You may need a different resolution for GRUB_GFX_MODE, and you don’t necessarily need the GRUB_THEME.

GRUB_CMD_LINUX="cryptdevice=UUID=device-uuid:crytplvm root=/dev/VolumeGroup/root resume=/dev/VolumeGroup/swap"

Now run the following to generate the bootloader.

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg

You should now have a working bootable system, but there is still some more setup to be done.

You should run passwd to give the root user a password. Later you should run sudo passwd -l root to remove the root password so that nobody can log in as root, but ONLY AFTER you are CERTAIN that at least one user has sudo access or you’ll have a real hard time.

So, setup a user account with sudo access.

visudo -f /etc/sudoers # and uncomment the sudo group
groupadd sudo # create the sudo group
useradd -m -G sudo,wheel -s /usr/bin/zsh username # create your user
passwd username # give your user a password

You should also set up the firewall now. I created the file /etc/nftables.conf with the following contents.

flush ruleset

table inet filter {
        chain input {
                type filter hook input priority 0;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # accept ICMP & IGMP
                ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
                ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept
                ip protocol igmp accept

                # activate the following line to accept common local services
                #tcp dport { 22, 80, 443 } ct state new accept
                udp dport { 5353 } ct state new accept

                # count and drop any other traffic
                counter drop

Also edit the line in /etc/nsswitch.conf to match the following so that avahi works properly.

hosts: files mymachines myhostname mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns

And create the file /etc/polkit-1/rules.d/49-allow-passwordless-printer-admin.rules with the following contents so regular users can configure printers.

polkit.addRule(function(action, subject) {
    if ( == "org.opensuse.cupspkhelper.mechanism.all-edit" &&
        return polkit.Result.YES;

Now you can enable all the services you want to be running when you reboot.

systemctl enable NetworkManager
systemctl enable lightdm
systemctl enable nftables
systemctl enable org.cups.cupsd
systemctl enable avahi-daemon

I also created the file /etc/X11/xorg.conf.d/30_touchpad.conf with the following contents so that my touchpad would work the way I like.

Section "InputClass"
    Identifier "libinput touchpad catchall"
    MatchIsTouchpad "on"
    MatchDevicePath "/dev/input/event*"
    Driver "libinput"
    Option "Tapping" "on"
    Option "NaturalScrolling" "true"
    Option "TappingButtonMap" "lmr"

Now is a good time to logout of the chroot environment, unmount the drives and reboot the machine.

umount -R /mnt

You’ll be asked for the password you used to encrypt the hard drive, then you’ll get to the login screen and you can log in as your user. i3 will generate a basic configuration for you. You can see mine here. Also, when you open a terminal zsh will run you through an initial setup to generate an initial .zshrc file. Again, you can see mine here.

Finally, I download and install cower to be able to more easily install packages from the AUR. I find cower strikes a nice balance between manually installing and maintaining packages from the AUR is a pain in the ass, and OMG I’m automatically installing untrusted software on my machine. Anyway, download and install as follows.

tar -xf cower.tar.gz
cd cower
makepkg -s
sudo pacman -U cower-18-1-x86_64.pkg.tar.xz
cd ../
rm -rf cower
rm cower.tar.gz

Then I use cower to install the Brave web browser, and laptop-mode-tools to help with laptop power management.

cower -d brave-bin
cd brave-bin
makepkg -s
sudo pacman -U brave-*.pkg.tar.xz
cd ../
rm -rf brave-bin
cower -d laptop-mode-tools
cd laptop-mode-tools
makepkg -s
sudo pacman -U lapt*.pkg.tar.xz
cd ../
rm -rf laptop-mode-tools
sudo systemctl enable laptop-mode

The default settings for laptop-mode-tools seem to be doing pretty well, but your mileage may vary, and you may want to adjust some settings. Just go find the documentation on the Arch Wiki.

I still have plenty of other software to install and tweaks to make, but things seem to be working well so far.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s