Minimal Ubuntu and i3 Setup

Here are notes I wrote down for setting up a minimal Ubuntu installation on a laptop, with i3 as the tiling window manager.

Why Ubuntu?

There are a plethora of linux distributions. Initially I wanted to use Debian because of its stability. The primarily purpose of this installation is to act as a host OS for multiple guest VMs. However, I decided to go with Ubuntu because of the vast community support and resources available online.

Why Ubuntu server?

Wanted to install the “desktop” libraries myself instead of using the default ones in the Ubuntu Desktop installer. Should be fine since from Ubuntu 12 onwards, desktop and server versions use the same kernel.


  • Ethernet connection (otherwise might run into wifi issues with Ubuntu Server installation)

Install Ubuntu Server

  1. Download installer.

    • First we need to download the installer. While we can use the main installer, the alternative installer allows us to do extra operations such as reusing partitions, which is what I needed.
    • I recommend just installing the alternative installer.
  2. Walk through installer, Make a root (/) and home (/home) partition.

  3. Reboot

Network (Optional)

Feel free to skip this section if you don’t need WiFi.

Switching from Ethernet to WiFi

There are many ways to configure wifi. Let’s pick the easiest approach and install the network-manager to help us configure wifi connection. Install the package and enable the service:

sudo apt install network-manager
sudo systemctl start NetworkManager.service
sudo systemctl enable NetworkManager.service

Disable systemd-networkd-wait-online check

Now that we have WiFi configured, we can ditch our ethernet connection and remove the cable. However now the wait-online service/daemon will hang during startup (probably because its looking for the ethernet connection). To avoid waiting too long (~2 minutes for me), let’s disable the service:

systemctl disable systemd-networkd-wait-online.service

and also prevent other services from starting it:

systemctl mask systemd-networkd-wait-online.service


Keyboard and Shell (optional):

Again, feel free to skip these if you satisfied with the current keyboard and shell. However in my opinion, the modifications below improve the experience of editing files in the terminal.


Personally I prefer switching CapsLock key with the left CTRL key. We can do that by modifying /etc/default/keyboard:


If too lazy to manually edit file, run this command:

sudo sed -i 's/XKBOTPIONS=""/XKBOPTIONS="ctrl:swapcaps"' /etc/default/keyboard

  • sed replaces lines that match the pattern. i.e. s/<text_to_replace>/<replacement_text>/.
  • -i saves the result into the same input file. Otherwise, by default, the result of sed are piped to stdout.

Change Shell

I prefer using zsh instead of bash for its auto completion features. Let’s install that right now:

sudo apt install zsh

Run zsh:


Follow prompt to save options. Example resulting .zshrc:

# Lines configured by zsh-newuser-install
setopt appendhistory autocd beep extendedglob nomatch
unsetopt notify
bindkey -e
# End of lines configured by zsh-newuser-install
# The following lines were added by compinstall
zstyle :compinstall filename '/home/ren/.zshrc'

autoload -Uz compinit
# End of lines added by compinstall

Finally, let’s change the default shell to zsh:

chsh -s /bin/zsh

Then logout and login to see changes.

Install Desktop

That was a lot of commands if you went through the optional sections; more is yet to come! Now let’s get started on the main task of configuring a lightweight desktop.

X Window System

We’ll need a display server so let’s install the one most widely used; Xorg:

sudo apt install xinit


  • Configuration files are stored in /etc/X11/xinit/.
  • If ~/.xinitrc is not specified, /etc/X11/xinit/xinitrc will run.
    • Same override logic applies for ~/.xserverrc.

For now, we don’t have to worry about adding any configuration for X.


Adding a terminal emulator

Because we plan on using a terminal in a GUI environment, we need to install a terminal emulator.

There are so many terminal emulators out there, all with varying degrees of features, quality, pouplarity, maintainability, etc. I suggest doing some research if you have the time and care strongly about which one to use.

I pesonally picked rxvt-unicode.

Changing terminal colors and font (Optional)

We can make the terminal easier on the eyes with base 16 color scheme. I You can choose whichever colour shceme you want; I chose solarized-dark-256.

Let’s fetch the dark color scheme and save it as ~/.Xresources:

curl >> ~/.Xresources
xrdb -load ~/.Xresources

And change the default font type and size by appending this to ~/.Xresources:

URxvt.font: xft:DejaVuSansMono:size=10

Tiling Window Manager

Now we finally get to installing the tiling window manager!

Similar to the situation with terminal emulators, there are quite a few window managers to choose from. I chose i3 because of its been in use for awhile, is well-known, and extensible (also easy potential migration to sway for future Wayland support).

sudo apt install i3

Now start X:


There will be prompts to create a config file, and to choose which key as yourkey. I just chose Yes and the default windows key.

Exiting i3

To exit i3, press <mod>-<shift>-e. Pressing ‘Yes’ with the mouse will stop the session.

If you didn’t install a terminal emulator previously, you might be frustrated that pressing the button doesn’t do anything. In this case, you’ll have to either: - Force shutdown and boot up your computer via power management (e.g, press and hold power button) - Go to another tty (virtual terminal) via <ctrl>-<alt>-<f2...?> and login. For my laptop, Fn2…Fn6 corresponds to tty2…tty6.

Improving the desktop experience (Optional, but recommended):

We officially have a minimal functioning desktop! However we’re missing a few common functionality that one expects from a desktop environment (screen brightness, sound, volume, etc.).

Here are some optional configuration for a better user experience.


  • can use xev to figure out keycodes of function keys.
  • Reload i3 config with <mod>+shift+c to test changes.

Screen Backlight

Now that we have i3 installed, we can add key bindings to adjust screen brightness.

First lets download and install a program to control backlights.
There is no package available in the main ubuntu repositories, so we have to download from github before installing:

curl -O -L
sudo dpkg -i light_1.2_amd64.deb

Unfortunately, at the time of writing, the debian package incorrectly installs the udev rules. However, this will be fixed in the latest release. Meanwhile, we can simply move the udev rules file over:

sudo mv /usr/lib/udev/rules.d/90-backlight.rules /lib/udev/rules.d/90-backlight.rules

Next, we can add the following keybindings to ~/.config/i3/config:

# increase brightness
bindsym XF86MonBrightnessUp exec "light -A 5"

# decrease brightness
bindsym XF86MonBrightnessDown exec "light -U 5"

reboot your computer to see the changes.

Screen Color Temperature

If the screen colors are bothering your eyes, we can adjust the color temperature with a program such as redshift:

sudo apt install redshift

Because redshift currently does not prepackage a systemd service file, we need to write our own.

Alternatively, we can simply start redshift when i3 is loaded. Add the following to the bottom of .config/i3/config:

exec --no-startup-id redshift


Lock screen/sleep

i3 comes with i3lock, which we can run on command line to bring up a lock screen. However, it would be nice if we could:

  • lock screen when computer goes to sleep
  • make sure locker doesn’t stay on forever (to avoid battery drain)

First let’s create the script to lock the screen. We’ll use the included i3lock locker. We also set dpms to reduce screen power consumption.

Create ~/.config/i3/ with the contents:

set -e
xset s off dpms 0 10 0
i3lock --color=333333 --ignore-empty-password --show-failed-attempts --nofork
xset s off -dpms

Dont’ forget to make it executable:

sudo chmod +x ~/.config/i3/

Now let’s install xss-lock, which simplifies hooking up locker program to events from X screen saver and systemd’s login manager.

sudo apt install xss-lock

Lastly, modify ~/.config/i3/config:

exec --no-startup-id xss-lock -- ~/.config/i3/

Optionally, we can also add a keybinding for locking screen: (I chose a function key)

bindsym XF86Tools exec --no-startup-id sleep 1 && xset dpms force suspend


External Monitor

For configuring screen layouts (including adding an external monitor), we can use xrandr for configuring display output(s).

We can use xrandr on CLI, but personally, I think a GUI would be easier to use for this type of task. We’re going to install arandr:

sudo apt install arandr


If we want sound, we can install Pulseaudio, which architectually sits atop of ALSA.

The PulseAudio Volume Control GUI is convenient to use, so let’s install it:

sudo apt install pavucontrol

Add keybindings to ~/.config/i3/config:

# increase volume
bindsym XF86AudioRaiseVolume exec "pactl set-sink-mute 0 false ; pactl set-sink-volume 0 +5%"

# decrease volume
bindsym XF86AudioLowerVolume exec "pactl set-sink-mute 0 false ; pactl set-sink-volume 0 -5%"

# mute volume
bindsym XF86AudioMute exec "pactl set-sink-mute 0 toggle"

Test volume:



  • Some apps, such as firefox, might require pulseaudio.

Autostart X after logging in on tty

It can be tedioius to always type startx when we login to our computer. We can write some small shell code to run the command on startup.

Add the following .bash_profile or .zprofile, depending on which shell you use:

if [[ ! $DISPLAY && $XDG_VTNR -eq 1 ]]; then

After exiting i3, user will remain logged in. If we don’t want to remain logged in, then use exec startx instead of startx.



This took longer than I thought it would, but now we have a custom, minimal, ubuntu distro on our laptop. Installing the distro and the tiling window manager was enough to have a bare, usable desktop. However, a lot more work was required to get closer to a typical desktop environment (wifi, adjusting screen, etc.).

Hopefully these notes are helpful in setting up your minimal desktop environment! Next time, we’ll look into setting up ZFS and KVM together for managing virtual machines.