Setting up a Linux Workstation for Software Development

All blog posts

Introduction

In my opinion, Linux is the best operating system for a software engineer, except they develop explicitly for Windows or MacOS. Whenever I read about new features for the Windows Subsystem for Linux, I wonder why people settle for anything less than the real thing. Linux aids many of my workflows with its customizability, the superior command-line experience, native support for containerization platforms, a dependable package management system, and many other features that I will describe in this blog post. MacOS comes close, but, in my opinion, falls short due to exorbitant hardware costs and less room for customization.

Still, as with any other operating system, optimizing a Linux workstation for software development requires some configuration. In this post, I will present tools and concepts that I think are very helpful, but overlooked by many. I will try to show only things that are not specific to my workflows, but rather useful for almost any software engineer, DevOps specialist, or just regular productivity enthusiast. Naturally, many of the configuration options and tools covered in this post are subjective. Nevertheless, I am confident that my suggestions are a good place to start. They have served me well over the years and I continually try to optimize my setup. Hence, I very much appreciate any improvement you might suggest.

Prerequisites

A Linux machine
For this guide, I will use Ubuntu 18.04, which is the current LTS release. Personally, I am quite satisfied with Ubuntu. Anything I don’t like can easily be changed. The biggest advantage over many other distributions is probably that the Ubuntu community is very active and it is usually easy to find people with similar problems. There is also a very active StackExchange community. However, most of the things covered in this post will be applicable to pretty much any Linux distribution and even MacOS.

Some command-line experience
Much of this post is intended for people who feel right at home when they see a ~- character. If you are not comfortable working with command-lines and have no intention to change this, you can still read the other sections though.

Tweaking Ubuntu

Before we start any serious work, I will point out some trivial changes to Ubuntu that I apply on all my machines.

Appearance

One of the first things I do after installing Ubuntu is to install the GNOME Tweak Tool:

sudo apt-get install gnome-tweak-tool

It enables complex modifications of the GNOME desktop environment. I recommend you play around with some of its options. For this guide, we will only consider the Appearance section. Specifically, we want to change the default Ubuntu theme to another one that provides better contrasts and an overall cleaner experience, namely the Adapta-gtk-theme, which is based on the Material Design guidelines.

sudo apt-add-repository ppa:tista/adapta
sudo apt-get update && sudo apt-get install adapta-gtk-theme

After installing the theme, you should restart the GNOME Tweak Tool and you can then select Adapta-Eta as your new theme. The theme comes with some nice benefits that you wouldn’t think of at first. For example, it fixes the ridiculously small toolbar icons in the Eclipse IDE.

Adapta Theme elements (Source).

Adapta Theme elements (Source).

The next thing I suggest is to change the Nautilus search behavior. With recent Ubuntu distributions, there is no type-ahead search in the standard file explorer. This means you can not start to type some letters and jump between files that start with these letters. Instead, Nautilus will enter a dedicated search mode that is confusing and quite slow for folders with a large amount of files.

Fortunately, we can easily get the old behavior back:

sudo add-apt-repository ppa:lubomir-brindza/nautilus-typeahead
sudo apt dist-upgrade
nautilus -r
Searching through my /bin folder by typing ahead (Source).

Searching through my /bin folder by typing ahead (Source).

There is a StackExchange answer that provides further details.

Hibernation

Another thing that is essential for me is hibernation. Usually, I will only shutdown my computer once a week or even less. However, I am not a big fan of suspending for long periods of time. Power outages could have unforeseen consequences and I simply feel a little better if my machines are off the grid altogether. Setting up hibernation is very simple with the hibernate package:

sudo apt-get install hibernate

Afterwards, you can simply do sudo hibernate to hibernate your machine.

Boosting Command-Line Productivity

I believe that command-line proficiency can significantly boost developer productivity. This is especially true in times of DevOps and NoOps, where developers are supposed to handle deployment pipelines and cloud infrastructure. Fortunately, there are some tools that can help you become a command-line wizard.

Shortcuts

Before going forward, I would suggest to setup some general terminal shortcuts. Simply go to Edit -> Preferences -> Shortcuts. I like to replicate web browser shortcuts for opening new tabs and windows, closing tabs, and cycling between tabs.

However, using this interface, it is not possible to set up Ctrl+Tab and Ctrl+Shift+Tab as tab switching shortcuts. Gnome has some issues with using the Tab key in shortcut configurations. Thanks to this answer from the Ubuntu community, we can get around this. Simply execute the following in your terminal:

gsettings set org.gnome.Terminal.Legacy.Keybindings:/org/gnome/terminal/legacy/keybindings/ next-tab '<Primary>Tab'
gsettings set org.gnome.Terminal.Legacy.Keybindings:/org/gnome/terminal/legacy/keybindings/ prev-tab '<Primary><Shift>Tab'

Switching from Bash to Zsh

A couple of months ago, I made an important change in my life. I switched from Bash to Zsh.

There are a lot of blog posts, threads, and articles that compare Bash and Zsh, e.g.:

At the end it boils down to one thing: Plugin and theme support

Zsh has an amazing themes and plugins ecosystem. Theme support allows to easily get a beautiful shell. Plugins range from simple auto-completion for all kinds of applications and tools(git, mvn, hugo, …) to complex stuff like improved search capabilities. Because of this fact alone, Zsh is superior to Bash.

However, chances are that you grew fond of Bash and that you get a bad feeling when somebody tells you that there is something better. I understand, it was the same for me. Still, I urge you to give it a shot. The transition is very painless since pretty much everything you like about Bash still works with Zsh. You will not have to learn new commands.

Installing Zsh

Installing Zsh on Ubuntu is very easy. We can just use the regular package manager:

sudo apt install zsh

Then, we set Zsh as our new default shell:

chsh -s $(which zsh)

Configuring Zsh History

For me there are few things worse than searching for an old shell command only to find out that the shell’s history size was set to a ridiculously low default number and that, because of this, the command was not saved.

Therefore, we extend the Zsh history size by putting this at the end of the ~/.zshrc configuration file:

HISTSIZE=10000000
SAVEHIST=10000000

For me, the command history is a tool to search for previous commands I might need now. I do not use it as a protocol for what I did when and in which exact order. Therefore, I use the following options to automatically get rid of all duplicates in my history:

## History command configuration
    
setopt HIST_IGNORE_ALL_DUPS # ignore duplicated commands history list

Also, I like to use multiple terminal sessions in parallel, potentially working on the same problem. For this, it helps a lot to share the same history among all sessions. It can be accomplished by

setopt SHARE_HISTORY # share command history data

If you are transitioning from Bash to Zsh, you probably want to keep your existing Bash history. In contrast to Bash, Zsh stores timestamps in its history file. Therefore, re-using the Bash history file does not work out of the box. Fortunately, all we need to do is to append some timestamp to all the commands from our previous Bash history and put the into the new Zsh history file. You could easily script this yourself or use one of the many good scripts that other people wrote, such as this one.

Zsh Features that are not in Bash

Once we have Zsh installed and finished our basic history configuration, we can start to take a look at some out-of-the-box features that make it stand out in comparison with Bash. If these do not impress you, keep in mind that the real big thing is plugin support, which I cover below.

Recursive Path Expansion

Zsh can do much more sophisticated expansions than Bash. This is documented in detail in the Zsh manual.

One feature that you can easily start to use is recursive path expansion. If you type cd /usr/local/b in Bash, you can then press Tab to expand this to cd /usr/local/bin. With Zsh, you can also type cd /u/lo/b and then press Tab. Zsh will recursively expand all path elements:

The above animation shows also that you can omit cd when changing directories.

Calculator: zcalc

Before switching to Zsh, I was often using the Python Shell as a calculator. However, this has a few downsides. Obviously, the Python Shell is not primarily developed to be a good calculator app. For example, simple operations, such as sqrt, require import statements, and there are no convenient ways to access results of previous lines.

The calculator script shipped with Zsh is a very simple and efficient solution. Before using it, it has to be loaded:

autoload -Uz zcalc

If you plan to use it often, you can add the autoload command to your ~/.zshrc.

Then, start the calculator with zcalc and do some calculations:

Results of previous operations can be accessed with the $-character.

Results of previous operations can be accessed with the $-character.

Advanced Aliasing

Zsh has some unique aliasing capabilities.

Suffix Aliases
This means you can assign applications to file suffixes, e.g. alias -s txt=vscode will allow you to open a .txt file with Visual Studio Code by just typing file.txt.

Global Aliases
Global aliases are set with the -g flag and allow to specify a replacement for any part of a command. For example, if you set alias -g G=' | grep' you will be able to do the following:

Installing ZSH plugins

Finally, it is time to explore the real strength of Zsh, which means installing plugins to boost our productivity above anything this anime character has ever seen before:

Package Manager: Oh my Zsh

A good place to start is to install Oh my Zsh, “a community-driven framework for managing your Zsh configuration.” Simply do:

wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh

Copy the template configuration file .zshrc.zsh-template in the .zshrc home directory and apply the configuration by executing the source command. Both can be done at once by executing the following line:

cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc

Oh my Zsh comes with many themes and plugins that we only have to enable in the configuration file in order to use them. In the next section, we will start by selecting a pretty theme.

Theme: Agnoster

Personally, I like the agnoster theme. It works well with the Adapta-Eta Gnome theme we have set previously.

In order to enable a theme, set ZSH_THEME to the name of the theme in your ~/.zshrc, in my case this is ZSH_THEME=agnoster. If you have troubles with special characters not being shown properly, install the Powerline font package:

sudo apt-get install fonts-powerline

The Oh my Zsh GitHub wiki provides a well curated list of available themes along with screenshots.

All pictures and animations of terminals you see in this post show the Agnoster theme with slight modifications to the prompt. In particular, I removed the git-part of the prompt and added a newline part instead. If you would like to replicate this, edit your ~/.oh-my-zsh/themes/agnoster.zsh-theme and replace the ## Main prompt part close to the end with the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
prompt_newline() {
  if [[ -n $CURRENT_BG ]]; then
    echo -n " %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR
%{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR"
  else
    echo -n " %{%k%}"
  fi

  echo -n " %{%f%}"
  CURRENT_BG=''
}

## Main prompt
build_prompt() {
  RETVAL=$?
  prompt_status
  prompt_virtualenv
  prompt_aws
  prompt_context
  prompt_dir
  prompt_bzr
  prompt_hg
  prompt_newline
  prompt_end
}

Basic Plugins

Next, you should enable some included plugins via adding them to your plugins setting in your ~/.zshrc file. After this step, it might look like this:

plugins=(colored-man-pages git python django mvn aws docker vscode)

You can browse all the plugins that come with Oh my Zsh in the official GitHub repository.

The above listed plugins are rather trivial, they simply provide command completion and define a set of aliases and shortcuts that come in handy when working with the respective tool. Nevertheless, this provides a real productivity boost. For example, finding out which git commands start with r becomes much simpler:

The original Bash history search always bothered me. Repeatedly pressing Ctrl+r and hoping to get lucky at some point is very cumbersome if you have lots of similar commands containing the query. To be fair, there are also great additions for Bash that improve this situation, such as McFly.

However, this is about improving history search with Zsh. I believe the best solution is using peco-history. It is a Zsh plugin that relies on peco to interactively filter through your history file. Peco is a general purpose interactive filtering tool that you can (and should!) also use as a stand-alone tool in your terminal. On Ubuntu, we can install it from the official repositories:

sudo apt-get install peco

Afterwards install peco-history:

git clone https://github.com/jimeh/zsh-peco-history.git ~/.zsh/zsh-peco-history

Then, put the following into your ~/.zshrc file:

source ~/.zsh/zsh-peco-history/zsh-peco-history.zsh

The plugin will be ready once you start a new terminal session.

The following animation shows that this improved history search was very helpful for writing this blog post. It allowed me to easily search for the exact commands I used when I set up my current machine:

Searching shell history with peco.

Searching shell history with peco.

Autosuggestions

Our new history search is great. The bad news is that we will not use it very often, because there is something that is even better in most cases: zsh-asutosuggestions
This plugin suggests completions for your commands as you type. By default, the suggested completion will be the first match in your history. This is how it looks like:

Using a suggested git command-line.

Using a suggested git command-line.

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

Afterwards, add zsh-autosuggestions to your plugins setting in your ~/.zshrc file:

plugins=(colored-man-pages git python django mvn aws docker vscode zsh-autosuggestions)

Syntax Highlighting

Another great plugin is zsh-syntax-highlighting. It highlights commands while you are typing them. This is especially useful for catching syntax errors. Once again, install via git:

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/

Then, add zsh-syntax-highlighting to your plugins setting in your ~/.zshrc file:

plugins=(colored-man-pages git python django mvn aws docker vscode zsh-syntax-highlighting)
Syntax highlighting also indicates whether a command is typed correctly.

Syntax highlighting also indicates whether a command is typed correctly.

Clipboard Tool

This one is not really a full-blown plugin. Oh my Zsh comes with a script called clipcopy out of the box. It is a simple tool that enables clipboard copy and past operations from the command-line:

<command> | clipcopy    # copies stdin to clipboard
clipcopy <file>         # copies the content of a file to clipboard

If you don’t use Oh my Zsh, you can get the same behavior via an actual plugin.

SSH Setup

One of the great advantages of using Linux instead of Windows is the out-of-the box SSH support. Immediately after installing your distribution, you can start to access remote servers.

However, there is some room for streamlining your SSH tasks. You can avoid lots of repetitive typing if you modify your .ssh/config file and setup meaningful defaults for the machines you access regularly:

Host ec2-instance # you can freely chose a name here that will act as alias for this host
    HostName <ip-address or hostname>
    User tkainrad


Host cluster # you can freely chose a name here that will act as alias for this host
    HostName <ip-address or hostname>
    User tkainrad
    IdentityFile `/home/tkainrad/cluster_rsa.pub`

For more sophisticated settings, look up the ssh_config man page.

If you want to go one step further, you can set up public key authentication so you can login to your most used remote hosts without having to re-enter your password each time. With ssh-copy-id, there is a simple tool that streamlines this process. If you have your hosts already configured via the .ssh/config file, just do

ssh-copy-id ec2-instance

By default, ssh-copy-id will take your public key in ~.ssh/id_rsa.pub. If you want to use different keys for each of your remote hosts, check out the man page page or this more extensive guide. If you use keys other than ~.ssh/id_rsa.pub you also have to add an IdentityFile entry to your .ssh/config settings. Afterwards, you will be able to access the machine by simply doing:

ssh ec2-instance

Additional Tools

A great terminal gets you a long way. However, there are some additional tools that can help make your workstation more complete. Naturally, there are many more tools and applications that could be helpful to you. In this section, I try to present some of my favorites that could be useful to almost anyone.

Text Editing: VSCode

For most of my more extensive software engineering projects, I use JetBrains products or Eclipse. I will not describe setting up those in this post, as this would easily mandate a separate article. However, I present a more lightweight editing environment that is often a better choice than to start up a full-blown IDE. For a software engineer, especially for one that deals also with DevOps workloads, it is daily business to edit and view all kinds of text-based files, such as .txt, .csv, .md, xml, .yml, and .json. For this, it is essential to have a fast text editor which can deal with large files and still provides sophisticated editing features.

Previously, I used Sublime. Since a couple of months now, I have switched to Visual Studio Code and I am still amazed by it. Comparing it to Sublime makes little sense in my opinion, because VSCode is just on a whole other level. Even for software projects with relatively simple technology stacks, such as this blog website, I now prefer VSCode over Eclipse or the JetBrains suite.

Screenshot of VSCode showing the default light theme (Light+) (Source).

Screenshot of VSCode showing the default light theme (Light+) (Source).

The easiest way to install Visual Studio Code on Ubuntu is to visit the official website and to download the Debian package. You could have probably figured out how to do this yourself, but do you also know how to set VSCode as the default application for all text files? Simply do

xdg-mime default code.desktop text/plain

This will spare you the headache of doing Right-Click -> Properties -> Open With -> Set as default on every file type separately.

Switching to VSCode from Sublime (or any other editor) is a surprisingly pleasant experience. VSCode will recommend the most relevant plugins as you go. For example, if you open a .py file, some extensions for Python development will be recommended. Installing them is then just a click away and doesn’t even require a restart of the application. After some days of following VSCode’s recommendations and occasionally searching for some extensions manually, my setup was more complete and efficient than it ever was with Sublime.

Sync Configuration Files: Mackup

So you just setup your desktop workstation, modified a bunch of configuration files, manually adjusted your VSCode keyboard shortcuts and now you want to do this also with your notebook?

The solution to this is one of my favorite tools of all: Mackup
It will use any software that is able to sync a folder, such as Dropbox, to keep your application settings in sync.

You can install it with pip:

pip install --upgrade mackup

Once installed, you can copy your application settings to Dropbox (per default) doing

mackup backup

To apply them at a different machine, just use

mackup restore

Behind the scenes, Mackup copies your configuration files to your Dropbox and then replaces the originals with symbolic links. Have a look at the GitHub Readme for more details.

Advanced Screenshots: Shutter

If you are coming from Windows, you probably use the Snipping Tool on a regular basis. With Screenshot, Ubuntu has a similar tool installed by default. However, there is another option that is superior to both the Windows Snipping Tool and the Ubuntu default: Shutter

sudo apt-get install shutter

It is very simple to use and does not force you to become familiar with its advanced features.

Pick Colors: Pick

If you do front-end development, chances are you need a color picking tool on your computer. The most commonly used tool on Ubuntu is GPick. However, it drives me crazy. Usually, I just want to pick a color and get the hex code into my clipboard. GPick makes this very hard. So instead, I recommend Pick, a simple and functional alternative.

Communication Hub: Station

Did you ever see someone using their phone while sitting in front of their personal computer? Chances are, they were using a communication app that they could have used much more efficiently from their larger device with an actual keyboard. To get the benefit of receiving all notifications from all my communication tools, and to be able to respond easily, I use Station. It is particularly useful if you have to monitor several Slack teams.

Screenshot of Station (Source).

Screenshot of Station (Source).

Record Short Screencasts: Peek

Did you wonder how I created those fancy gifs showing my terminal? I thought so.

Peek is a very lightweight and simple tool to record short screencasts. To install it on Ubuntu do

sudo add-apt-repository ppa:peek-developers/stable
sudo apt update
sudo apt install peek
Peek in action. (Source).

Peek in action. (Source).

During the creation of this post I was made aware by a good friend and fellow software engineer of dedicated terminal recording tools, such as Terminalizer and asciinema. However, these require some initial setup work, especially if you want to show off a theme and require that your animated terminal looks exactly like your actual terminal.
Since I already recorded most of the animations, I decided to stay with Peek for this post. Nevertheless, if your use case is terminal recording, you should probably go with one of the linked projects instead of Peek.

Mail Client: Thunderbird

For mail, I use Thunderbird. I don’t particularly like it, but to my knowledge it is still the best desktop email client for Linux. Unfortunately, some minor design decisions make the program almost unusable for me in its default state. The reason I include this section about a software that everyone knows already is mainly to highlight three changes I always make to the default setup:

  1. Install the No Message Pane Sort by Mouse add-on. With this extension, a click on the mail list table header will no longer change the defined sort order. Without it, misclicks while trying to select the first mail in the list are very annoying. Personally, I never want to change the sort order at all. However, it is still possible by holding Ctrl while clicking.
  2. Install the Search Results Sort By Date Not Relevance add-on. By default, Thunderbird applies some kind of Relevance-based sorting to your search results. To me, this feels very counterintuitive. With this extensions, your search results will be sorted by date.
  3. Finally, go to Preferences -> Composition and uncheck the Use Paragraph format instead of Body Text by default to prevent Thunderbird from adding absurd amounts of whitespace whenever you press the Enter key while composing a mail.

If you know of a new fancy alternative to Thunderbird that handles parallel usage of several mail accounts well, please let me know.

Bonus Tip

If you have read this far, I am willing to share my most secret Linux hack with you. Joking aside, it is very helpful to know what to do when your Linux workstation freezes. For some reason, I did not until a couple years ago. Maybe the following trick can help you to avoid some forced restarts in the future:

The most flexible way to re-gain control of a system that has frozen completely is pressing Ctrl-Alt-F3. Then, use top and other process monitoring tools to find the process IDs of the faulty processes. Then, simply kill them (e.g. type kill <pid>. Afterwards you can get back to your work using Ctrl-Alt-F1 (Source).

Conclusion

I hope this post showed you some tools or practices that you didn’t know yet. I have had a good experience with all of them. Especially switching from Bash to Zsh and installing the described plugins came with a real productivity boost. If you feel that I left out something important, I’d be very interested to hear your suggestions.

If you are not mainly using Linux yet, the length of this post might give the impression that it is still a pain to set up a proper Linux workstation. However, you do not necessarily need all of the things I showed here. Also, everything covered in this post is very easy to install with minimal configuration overhead. I strongly believe that you would have a much harder time setting up a comparable Windows development workstation.

You can still spend your life setting up Linux. However, if you use a popular, well supported distribution you definitely don&rsquo;t have to. (Source: xkcd.com)

You can still spend your life setting up Linux. However, if you use a popular, well supported distribution you definitely don’t have to. (Source: xkcd.com)

Share via
comments powered by Disqus