Posted on February 17, 2015

Sanity with Arch Linux and xmonad

In a world where most Linux users revolve around Ubuntu and desktop environments choices (Gnome vs KDE vs …), I’m feeling more and more attracted to something simpler and more lightweight. And even though my installations of KDE and Gnome were done on a very light Debian system, with almost everything stripped off, I noticed that they could be even more light: they have more widgets than I need, and more applications than I ever used.

Besides that, my attempt at having a rolling distribution of Debian by pointing it to testing, also meant that my system was far more unstable than I wanted. I got a rolling distribution but I got a broken system every once in a while.

So I rethought all these constraints and how to accomodate them better with a new distribution. Here’s what I want:

So after some reading and experimenting, I decided to go with Arch Linux and xmonad.

Many things contributed to this decision but for sure documentation was one of the main ones for Arch. I had bumped into their wiki accidentally many times before while trying to solve problems on Debian and the quality is quite good.

As for xmonad, the choice was essentially based on the fact that it was implemented in Haskell, which gives me a chance to play with the source code. The fact that it is super light on resources definitelly helped, but to be honest I did not look into other alternatives.

So here I am, 24 hours later, writing this blog post on Emacs running on Xmonad on a fresh and light Arch Linux installation. The rest of this post explains how to do it.

What you should be aware of

Depending on your experience, Arch Linux may be a bit too manual for your taste. You should definitelly read the begginer’s guide, the FAQ and the installation guide beforehand - the documentation is well written and it gives you a general idea of all the steps you’ll have to go through, which are somewhat different from a Debian instalation for example.

There are a few things I think you should prepare ahead of time, even before burning the installation CD, and the docs don’t really mention:

  1. Find out if your BIOS uses UEFI or not as this is very relevant for the bootloader installation. It will depend on things such as whether you have other operating systems installed or not or if you plan to do it eventually;
  2. Find out to what is your BIOS time synchronized to. Is it UTC or local time?
  3. Partition your hard disk before you even start this whole process. This one I cannot stress enough – get a gparted Live CD (or whatever you prefer), boot into your computer and prepartition it. You’ll get the benefit of doing it in a controlled environment, thinking well ahead of time about how you want to have your partitions. Oh and do write down what is each partition, i.e., /dev/sda5 is /, /dev/sda6 is /boot, etc.
  4. Definitelly do this with the instructions printed or opened on another laptop so that you can search for help if you get stuck.

The base system

The CD can be downloaded from Arch linux downloads page. Partition your disk, burn Arch into a CD and boot into it. You’ll have a menu at boot time and then you’ll be logged in as root in a prompt.

Activate the keymap you want if you don’t want US english. In my case, for Portuguese:

Since we already partitioned the disks, let’s format them. In my case, I had 2 extended partitions (sda5 and sda6) under a logical partition, after the Windows 8 partitions:

Let’s mount the partitions. The partition which is going to be / should be mounted on /mnt.

Now we install the base system onto /mnt. We’ll first vi /etc/pacman.d/mirrorlist and leave only the best mirrors. I left all the ones until 1.5 since those included a lot of germany and european mirrors, and removed all US mirrors. It’s important to note that, since I was on a wired connection, the next step works automatically for me. I haven’t tried this on a wireless connection but the documentation explains how to do it.

This part takes a little bit. When that’s done it’s time to switch to the newly installed system and finish setting it up:

This part of the configuration will surely be different for you but my examples will indicate what you should be doing on your computer:

Now it’s time to install the boot loader. This will definitelly be different for you if you decide to put GRUB on the beggining of your disk. In my case, it’s in the beggining of sda5 since Windows won’t cope well with it and for that I had to do some more magic:

Finally we give a password to root, exit bash and the chroot shell, unmount the system and reboot:

If you did everything well, you’ll see an Arch Linux prompt after reboot, indicating that you just installed your system! Congratulations! So what do you have at this moment?

So since we intend to get an X windows system with xmonad, emacs and Haskell ready, we need a few base things before that:

Fish and adding a user

Let’s start with a few basics, like not using root for everything:

Let’s get Fish as well, so that we can define it as the shell for our new user:

If Fish is working fine for root, we add the new user:

I’ll leave the configuration of emacs to another post. For now we have already a sane text editor so let’s keep it at that.

nVIDIA Driver

We can check that the nVIDIA driver works ok even without having X Windows, so let’s do that:

The console will now show up in 640x480 resolution so let’s change that to something nicer. For that we need to know what resolutions our graphics card can handle and for that we need a tool called hwinfo

The output will look something like this:

02: None 00.0: 11001 VESA Framebuffer
[Created at bios.459]
Unique ID: rdCR.y3YwIxtOSHA
Hardware Class: framebuffer
Model: "NVIDIA GK110 Board - 20830010"
Vendor: "NVIDIA Corporation"
Device: "GK110 Board - 20830010"
SubVendor: "NVIDIA"
SubDevice:
Revision: "Chip Rev"
Memory Size: 14 MB
Memory Range: 0xf1000000-0xf1dfffff (rw)
Mode 0x0300: 640x400 (+640), 8 bits
Mode 0x0301: 640x480 (+640), 8 bits
Mode 0x0303: 800x600 (+800), 8 bits
Mode 0x0305: 1024x768 (+1024), 8 bits
Mode 0x0307: 1280x1024 (+1280), 8 bits
Mode 0x030e: 320x200 (+640), 16 bits
Mode 0x030f: 320x200 (+1280), 24 bits
Mode 0x0311: 640x480 (+1280), 16 bits
Mode 0x0312: 640x480 (+2560), 24 bits
Mode 0x0314: 800x600 (+1600), 16 bits
Mode 0x0315: 800x600 (+3200), 24 bits
Mode 0x0317: 1024x768 (+2048), 16 bits
Mode 0x0318: 1024x768 (+4096), 24 bits
Mode 0x031a: 1280x1024 (+2560), 16 bits
Mode 0x031b: 1280x1024 (+5120), 24 bits
Mode 0x0330: 320x200 (+320), 8 bits
Mode 0x0331: 320x400 (+320), 8 bits
Mode 0x0332: 320x400 (+640), 16 bits
Mode 0x0333: 320x400 (+1280), 24 bits
Mode 0x0334: 320x240 (+320), 8 bits
Mode 0x0335: 320x240 (+640), 16 bits
Mode 0x0336: 320x240 (+1280), 24 bits
Mode 0x033d: 640x400 (+1280), 16 bits
Mode 0x033e: 640x400 (+2560), 24 bits
Mode 0x034b: 1920x1080 (+1920), 8 bits
Mode 0x034c: 1920x1080 (+3840), 16 bits
Mode 0x034d: 1920x1080 (+7680), 24 bits
Mode 0x0360: 1280x800 (+1280), 8 bits
Mode 0x0361: 1280x800 (+5120), 24 bits
Config Status: cfg=new, avail=yes, need=no, active=unknown

You’ll find some hexadecimal number on the column on the left which you should convert to decimal. In my case, the mode I was interested in was 1280x1024x24, which is 0x031b, which is 795 in decimal. That number should now be added to /etc/default/grub plus the following changes:

X windows and xmonad

We’ll be installing a window manager, as opposed to a full desktop environment. It’s a good idea to understand the differences between the two. For me, the main reason to go for a window manager was really performance.

Let’s create our nVIDIA configuration file at /etc/X11/xorg.conf.d/20-nvidia.conf with

Section "Device"
    Identifier "Nvidia Card"
    Driver "nvidia"
    VendorName "NVIDIA Corporation"
    Option "NoLogo" "true"
EndSection

I also configured my keyboard in X windows to be in portuguese plus I made the Caps Lock key and alternative to CTRL key (for emacs) and I set CTRL+ALT+Backspace as the combination to kill X Windows:

Next I configured the terminal to use the inconsolata font by creating ~/.Xresources with the following:

XTerm*reverseVideo: on
xterm*faceName: Inconsolata:size=10:antialias=true

We’re almost done. We now get xmonad and configure it:

The default configuration is a bit too white so let’s change it. These changes are based upon several guides and tutorials found on the xmonad page, on the Haskell wiki and on the Arch Linux Wiki. They represent the bare minimum for me but, as with everything in this post, YMMV.

It uses xmobar to have a small text based bar on the top of the screen and a background image. Nothing more.

Let’s edit ~/.xmonad/xmonad.hs and add the following Haskell code (remember to replace my references to /home/luis with your home directory):

import XMonad
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.DynamicLog
import XMonad.Util.Run
import XMonad.Util.EZConfig

main = do
xmproc  manageHook defaultConfig
    , layoutHook = avoidStruts  $  layoutHook defaultConfig
    , logHook = dynamicLogWithPP xmobarPP
    { ppOutput = hPutStrLn xmproc
        , ppTitle = xmobarColor "green" "" . shorten 50 }
    } `additionalKeys`
    [ ((mod4Mask .|. shiftMask, xK_z), spawn "xscreensaver-command -lock") ]

We’ll also edit ~/.xmobarrc and add:

Config { font = "-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*"
    , bgColor = "black"
    , fgColor = "grey"
    , position = TopW L 100
    , commands = [ Run Weather "EDDB" ["-t","<station>: <tempc>C","-L","5","-H","30","--normal","green","--high","red","--low","lightblue"] 3600
        , Run MultiCpu ["-t","<autototal>","-L","5","-H","50","--normal","green","--high","red"] 50
        , Run Memory ["-t","Mem: <usedratio>%"] 0
        , Run Date "%a %b %_d %H:%M:%S" "date" 10
        , Run StdinReader
        ]
    , sepChar = "%"
    , alignSep = "}{"
    , template = "%StdinReader% }{ %multicpu% | %memory% | <fc>%date%</fc> | %EDDB%"
}

Finally, find an image you like for background (I’m currently using this one), download it and edit you ~/.xinitrc:

#!/bin/sh
#
# ~/.xinitrc
#
# Executed by startx (run your window manager from here)

if [ -d /etc/X11/xinit/xinitrc.d ]; then
    for f in /etc/X11/xinit/xinitrc.d/*; do
        [ -x "$f" ] && . "$f"
    done
    unset f
fi

# Xresources
[[ -f ~/.Xresources ]] && xrdb -merge ~/.Xresources

# Set the background Image
feh --bg-fill ~/dot/lambda.jpg

# start xscreensaver
/usr/bin/xscreensaver -no-splash &

# Start xmonad
exec xmonad

At this point startx should start xmonad and show you your downloaded image as background.

And there you have it!

This is a very very bare bones configuration which is supposed to be iterated. There’s still many things that can be done on top of this, for example:

In the meantime, if you want to peek into some of these files, check my dot files repository on github.

For now the foundation is laid - a very minimal and super fast Linux with a windowing system which just gets out of the way. :-)