skip to main content

Fresh Debian Testing setup with bspwm

This is a comprehensive post that describes in detail:

  1. installing Debian Testing via NetInstall freshly on a Thinkpad X220 machine
  2. setting up a tiling window manager bspwm for a minimal and functional Linux desktop experience.

A minimal and functional desktop experience means a tiling window manager in the Unix-verse. I used dwm several times in the past and and briefly considered using i3wm, but I have chosen to go with bspwm (Binary Space Partition Window Manager).


I bought a used X220 in 2016 and installed BunsenLabs Linux, a successor to Crunchbang Linux. BunsenLabs improves the desktop experience for the average Linux user by providing a usable desktop environment and some other sane defaults. However, it did not have a Debian Testing based version. It is bound to have some package or dependency conflicts or breakages if one upgrades to Debian Testing.

Shortly after, I upgraded to Debian Testing to have access to the then-latest node and python versions. Since then, I have been using this laptop as a daily driver and a developer machine. Never faced any big challenges through all the dist-upgrades and software installations and usages. However, the aforementioned breakage or a conflict was just around the corner waiting to strike.

Around this time last year, I dist-upgraded my Thinkpad X220 as usual. I rebooted immediately after and I could not see tint2 and conky panels. Some keyboard shortcuts stopped working. The machine became practically unusable.

It has been too long since I had fun with computers. I knew I had to step up the game. No, not Archlinux, but base Debian. Familiarity is my biggest factor to stay with Debian. I wrote about it several years ago.

Looking back, it was a wonderful four years of Linux. My sincere and heartfelt thank you to BunsenLabs maintainers and the community.


Next step for me is to define what I want for a minimum of 5 years. So, I identified two high-level goals:

  1. Use Debian Testing
  2. Use a tiling window manager

Let's go through some pre install steps before proceeding with the install.

Pre install

  1. Backup necessary files to Dropbox or similar solutions. Backup media and large files to cloud storage or external storage disks. This is a basic backup strategy and it works. If you have a proper backup routine and strategy, then more power to you. I used an external SSD.
  2. Push unpushed commits to github or gitlab or your favorite hosted git server. In my case, I ran git status in all code/project directories.
  3. Take a list of software using apt-mark showmanual. Save it on your backup or a USB flash drive. This can help you take stock of currently installed software.
  4. Do a full cleanup of the machine using bleachbit. This should be enough to make the machine ready for the OS reinstall. This step is not required and does not probably make any difference, but it is a personal habit.
  5. Make an install media. We need a lower-capacity USB flash drive (<4GB) to format it with the netinst ISO. To do this, download and run unetbootin.exe on your Windows machine. Then, select Debian as the distribution, and Stable_Netinstall_x64 as the version. Select OK to proceed to write this ISO to the drive. This will take a minute or two. The install media is ready now.
  6. Acquire missing firmware. Thinkpad X220 requires some missing firmware files: iwlwifi-6000g2a-6.ucode and iwlwifi-6000g2a-5.ucode. Download these from Extract and place them on the USB flash drive. This might be different for your machine. A search should help you figure out the exact firmware required.

Connect laptop to LAN cable, insert the flash drive and boot the laptop. Upon boot, you will see the installer starts the process. If you are doing this on an existing install, then you will see GRUB menu before the installer comes up.

Installation is a series of choices we select to configure the system the way we want. Next, let's go through the process of a Debian NetInstall installation process.

Install Debian

I did not find a way to retain the screenshots while doing the netinstall. So I logged only the steps in text. First option is to select a language for your OS.

Select a language: English

Select your location: India

Configure your keyboard: American English

Configure the network:

  1. Primary network interface:
    1. Intel Corporation Gigabit Network Connection
  2. Hostname:
    1. garuda
  3. Domain name:
    1. empty

Choose a mirror of the Debian archive

  1. Debian archive mirror country:
    1. India
  2. Debian archive mirror:
  3. HTTP proxy information:
    1. empty

Set up users and passwords:

  1. Root password:
    1. R00tP@s5
  2. Full name for the new user:
    1. First Last
  3. Username for your account:
    1. ab
  4. Choose a password for the new user:
    1. myP@ss

Partition disks:

  1. Partitioning method:
    1. Guided - use entire disk and set up LVM Note: Select Guided - use entire disk if you are completely new or forgot about this stuff
  2. Select disk to partition:
    1. select your hard drive/SSD instead of USB drive
  3. Partitioning scheme:
    1. Separate /home partition Note: Select All files in one partition if you are completely new or forgot about this stuff
  4. Remove existing logical volume data
    1. Yes
  5. Write the changes to disks and configure LVM
    1. Yes
  6. Amount of volume group to use for guided partitioning:
    1. accept the full size it provides
  7. Write changes to disks
    1. Yes

This takes a while.

Configuring popularity contest No

Software selection. Unselect everything except the print server and standard system utilities. This will leave you without any desktop environment and a window manager. This way you could go for a tiling window manager without the burden of a full blown window manager.

Select the following options

[*] print server [*] standard system utilities

This takes a while.

Install the GRUB boot loader on a hard disk

  1. Install the GRUB boot loader to the master boot record?:
    1. Yes
  2. Device for boot loader installation:
    1. Select the same harddrive/SSD instead of USB drive as in step 7.2.1. In my case it is /dev/sdb.

Let the installation finish. After the installation finishes, you will see a countdown. At this point, press Continue and when the system is booting up, remove the USB drive before the GRUB shows up.

Post install

On the GRUB screen at boot, the option Debian GNU/Linux is automatically selected, unless we want to do something advanced. In which case, you can press down arrow to go into advanced options.

After a successful boot, we will come to a login shell. Input your username and password.

Debian GNU/Linux 11 garuda tty1
garuda login: _

After a successful login, you will see the prompt.

ab@garuda:~$ _

The first thing we need is to change the OS sources to track the Testing version instead of Stable. If you recall, we used the Stable_NetInstall_x64. We could have used Testing_NetInstall_x64 right? For some real reason, this doesn't work. I have tried it a few times and always had to come back and use the Stable ISO and then upgrade to Testing after installation.

Now, let's update the sources.

Update sources

Sources in the Linux world mean the OS level package registry feeds. We can find them in the etc/apt/sources.list file.

Let's use a sources generator website, instead of making modifications to this file by hand. Go to Sources List Generator for Debian. It features the official Debian repositories as well as other 3rd party repos. Select Debian Testing and any other software repositories as per your need.

The website helpfully reminds us to install a few base packages before we proceed with updating the sources. Login as root.

$ su - root
$ apt install curl wget apt-transport-https dirmngr

The package apt-transport-https might not be needed it seems, but at the time of this writing I did not know any better. So I included it.

Copy the sources list from the website and update them in the sources file:

$ nano /etc/apt/sources.list

It should look this more or less.

###### Debian Main Repos
deb testing main contrib non-free
deb-src testing main contrib non-free

deb testing-updates main contrib non-free
deb-src testing-updates main contrib non-free

deb testing-security main
deb-src testing-security main

Run update command:

$ apt update

471 packages can be upgraded. Run 'apt list --upgradable' to see them
$ apt full-upgrade -y

This took about a minute to download and then three to unpack and install. Now, we are tracking Debian Testing.

Since we want to install some graphical programs like browsers, code editors etc., we need something called a window manager. Before we do that, note that we are still inside the login shell. A login shell is like being inside an SSH session of a server.

Login shell by default has a smaller font size.

Login shell font

Login as root and run the following command to configure the login shell font

$ su - root
$ dpkg-reconfigure console-setup

Screen 1 - Encoding to use on the console: UTF-8 OK

Screen 2 - Character set to support: Guess the optimal character set OK

Screen 3 - Font for the console: Let the system select a suitable font OK

Screen 4 - Font size: 12x24 (framebuffer only) OK

If you don't like the look afterwards, try again with other combinations. You may need to restart the service and/or reboot the machine. In my case, I did not need to do that.

$ su - root
$ service console-setup restart
$ systemctl reboot

Now, we are ready to install and configure the window manager bspwm.

Setup window manager

The foremost requirement for any GUI application on Linux is a display server. There are few of these but the most common is Xorg. Let's install that as root.

$ su - root
$ apt install xorg
$ exit

This will also install the package xinit which is what we will require to start the window manager.

Create a file .xinitrc in your home directory

$ touch .xinitrc
$ nano .xinitrc

Add the following statement in this file

exec bspwm

Now we can install bspwm and a few helpful companion packages.

bspwm is available in Debian package repository, but we could also go for the latest and the greatest version by building it from sources.

Login as root and install bspwm, polybar and dmenu and remove lemonbar. Polybar is a customizable status bar to display CPU Usage, RAM usage, desktops, date and time etc and dmenu is a minimal program launcher. Lemonbar is a status bar that comes with bspwm and is not required since we are setting up polybar.

$ su - root
$ apt install bspwm polybar dmenu
$ apt autoremove lemonbar

We also need a package called sxhkd for configuring keybindings. This should be automatically installed when bspwm is installed. Take note of the new packages line and you should spot it toward the end.

Now that the installation is done, let's configure bspwm, polybar and sxhkd for a minimal initial experience. All three programs come with some sample configuration files bundled. Copy them over to your home directory as root.

$ su - root
$ cp /usr/share/doc/bspwm/examples/bspwmrc /home/ab/.config/bspwm/bspwmrc
$ cp /usr/share/doc/bspwm/examples/sxhkd /home/ab/.config/sxhkd/sxhkdrc
$ cp /usr/share/doc/polybar/config /home/ab/.config/polybar/config
$ exit

Make bspwmrc and sxhkdrc executable.

$ chmod +x /home/ab/.config/bspwm/bspwmrc
$ chmod +x /home/ab/.config/sxhkd/sxhkdrc

Take a look at the bspwmrc. In the first line, we ensure the hotkey daemon is running and then configure a few bspwm rules using an included client utility bspc. I removed all bspc rules to include only Chromium and Firefox. These two rules state that Chromium opens on second desktop and Firefox on third.

#! /bin/sh

pgrep -x sxhkd > /dev/null || sxhkd &

bspc monitor -d a b c

bspc config border_width         1
bspc config window_gap          5

bspc config split_ratio          0.52
bspc config borderless_monocle   true
bspc config gapless_monocle      true

bspc rule -a Chromium desktop='^2'
bspc rule -a Firefox desktop='^3'

Next, take a look at the sxhkdrc. Super key is the windows key. I opted to use Alt key as the modifier key. If we want to do that, replace super with Alt in this file. I list hotkeys for only these 5 essential actions here , but the file has more hotkeys which we can study later.

  1. Launch the terminal
  2. Launch the program launcher
  3. Reload sxhkd after a config change
  4. Reload bspwm after a config change
  5. Quit bspwm
# wm independent hotkeys

# terminal emulator
super + Return

# program launcher
super + @space

# make sxhkd reload its configuration files:
super + Escape
    pkill -USR1 -x sxhkd

# bspwm hotkeys

# quit/restart bspwm
shift + super + {q,r}
    bspc {quit,wm -r}

# close and kill
super + {_,shift + }w
    bspc node -{c,k}

# alternate between the tiled and monocle layout
super + m
    bspc desktop -l next

. . .
. .

Change the default urxvt terminal to the terminal of your choice. I use sakura terminal.

Start the window manager.


If everything is setup correctly, we will see a black screen and nothing more. Launch a terminal or two by pressing Alt+Return (or super, if we didn't change this) to ensure everything is fine. It should look like this.

Next, let's configure polybar and launch it with bspwm. Open polybar config. I have only included here the most important properties to configure first. Colors, bar name (bar1 in this case), font-0 font size, and modules. I settled down to using these modules alsa, memory, cpu, eth, wlan, temperature, and date. There are many more modules we can find on polybar wiki.

background = #222
background-alt = #444
foreground = #dfdfdf
foreground-alt = #999
primary = #ffb52a
secondary = #e60053
alert = #bd2c40

width = 100%
height = 27
radius = 3.0
fixed-center = false
bottom = true
background = ${colors.background}
foreground = ${colors.foreground}

font-0 = fixed:pixelsize=12;1

modules-left = bspwm
modules-center =
modules-right = alsa memory cpu eth wlan temperature date

Full config here:

Create a script along side polybar config.

$ cd .config/polybar
$ touch
$ nano

Update the file as such.

killall -q polybar

while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done

polybar bar1 2>&1 | tee -a /tmp/polybar-bar1.log & disown

Make it executable.

$ chmod +x

To start polybar with bspwm, include the line $HOME/.config/polybar/ at the top of bspwmrc.

#! /bin/sh

pgrep -x sxhkd > /dev/null || sxhkd &

bspc monitor -d a b c

. . .
. .

That is the bare minimum needed for us to get started with a functional desktop. Press hotkey Shift + Alt + R to reload bspwm.

This is how it looks now if everything works fine. Take a look at polybar below — we have three desktops on the left, nothing in the middle and system information and date on the right.

Here are three other hotkeys to keep us sane for the first few days.

Alt + ]        Switch to desktop on the right
Alt + [        Switch to desktop on the left
Alt + Tab      Switch to the last desktop

Setup essentials

There are a few things that could make our installation slightly more comfortable to use.


If we configure our user as a sudoer, then we could do sudo command instead of logging in as root each time.

$ su - root
$ apt install sudo
$ usermod -aG ab sudo

Logout of session by pressing Shift + Alt + R and then Ctrl + D. Login again for this to take effect.


Install a terminal of your choice. I prefer sakura, it is lighter than tilix and terminator, loads fast and has basic configurability.

$ sudo apt install sakura

Web browser

Let's install Chromium and Firefox.

Chromium has two uses for me - Download Firefox and test websites occasionally. Firefox has been my main browser for more than 17 years. I always install it on the first day. I use it even for all my web development purposes.

Chromium has a package, so installing it is just one command away.

$ sudo apt install chromium

Firefox does have a package called firefox-esr in the package archive, but it is several versions behind the current version. Installing the current version is slightly more involved than Chromium, but it is a minor pain point considering the benefits.

To install current version of Firefox, download it from Move the archive to /opt, extract the archive and make a symlink from /opt/firefox/firefox to /usr/local/bin/firefox. This way you could use the launcher to type firefox and launch it.

$ sudo apt install libdbus-glib-1-2
$ sudo mv /home/ab/Downloads/firefox-89.0.2.tar.bz2 /opt
$ cd /opt
$ sudo tar xjf firefox-89.0.2.tar.bz2
$ sudo ln -s /opt/firefox/firefox /usr/local/bin/firefox

Package libdbus-glib-1-2 is required for Firefox to work on an install without a full fledged desktop environment.

Next, set Firefox as default.

$ sudo update-alternatives --install /usr/bin/x-www-browser x-www-browser /opt/firefox/firefox 200
$ sudo update-alternatives --set x-www-browser /opt/firefox/firefox

To update Firefox, download the latest archive

$ sudo mv /home/ab/Downloads/firefox-90.0.tar.bz2 /opt
$ cd /opt
$ sudo rm firefox-89.0.2.tar.bz2
$ sudo tar xjf firefox-90.0.tar.bz2


$ sudo apt install mlocate

mlocate is a package to find files from all corners of your system. Occasionally, we need to run sudo updatedb to update its search indexes.


Sound is non existent so far. Install alsamixergui (or alsatools) to fix this.

$ sudo apt install alsamixer

Launch alsamixer from terminal.

Press MM on master and speaker to unmute

After doing this, I could play a youtube video on Chromium to verify that sound is working. The interesting thing is that I couldn't do the same from Firefox. To fix this I installed pulseaudio the package.

$ sudo apt install pulseaudio

That is it, we are done. We now have a minimal and functional Linux desktop environment. We can manage our system, configure packages, browse websites and maybe write some code.

Here is a glimpse of bspwm's power.

Learning go with chromium, geany and terminal.


In reality, this is a beginning rather than a conclusion. A fresh Linux install always improves mood and boosts confidence. Though I don't expect X220 to last a decade from now, I will utilize it to build some hobby and even some of my serious projects as long as it runs.

In a next set of posts, I will setup more useful software, setup development environments and explore bspwm in more detail.

Some references: