Ubuntu Developer Setup With Bare Essentials
Ubuntu Linux is a fanstastic operating system for writing wide variety of code, possibly anything that is not MacOS or iOS code. While my desktop computer is usually a Mac, I always find myself having a bunch of Ubuntu servers running for various types of coding. Whether it is a Raspberry Pi (LOVE THEM!) with 8GB of RAM, or a small but super-fast (for what it is) HP EliteDesk 800 G5, bought second-hand on eBay, with upgraded 64GBs of RAM, or a bunch of small servers on various cloud providers - developer environments on Ubuntu are a constant presence. And that doesn’t even include servers that actually run anything public-facing.
With these many Ubuntu servers, I find myself configuring some basics on them, all the time. Following is a highly-opinionated walk-through of what and how I usually configure before I even get to things like Docker and Kubernetes.
1. Mosh Instead of SSH
Mobile Shell (Mosh) is, arguably, an improved variant of SSH, in that it is extremely resilient towards network interruptions. You can install it and configure firewall to allow Mosh traffic on the server, with the following code:
> sudo apt-get install mosh
> sudo ufw allow mosh
2. Zsh Instead of Bash
I spent decades using Bash and over the years developed a very elaborate configuration that met my needs very closely, so I was super hesistant to switch to Zsh, even after MacOS made the latter default. However, after finally spending enough time with Zsh and its extremely flexible, rich, and configurable Oh My Zsh extensions, it became clear that even two decades of one person making shell comfortable for themselves cannot match with a vibrant community investing into the same. I am a happy convert now, so the next thing I do is - install zsh and configure it to my liking using enormous wealth of plugins provided by Oh My Zsh.
First, let’s make sure it is installed:
> sudo apt-get install zsh
> zsh --version
zsh 5.8
Make zsh the default shell (instead of bash):
> chsh -s $(which zsh)
Password:
> exit
Please make sure that “chsh” command is run as your non-privileged user and not with sudo
, otherwise you
will make root’s shell zsh, and not yours.
Once you install and enable zsh, you need to exit and re-login to launch it for the first time. Zsh requires certain amount of configuration when you first launch it:
This is the Z Shell configuration function for new users,
zsh-newuser-install.
You are seeing this message because you have no zsh startup files
(the files .zshenv, .zprofile, .zshrc, .zlogin in the directory
~). This function can help you with a few settings that should
make your use of the shell easier.
You can:
(q) Quit and do nothing. The function will be run again next time.
(0) Exit, creating the file ~/.zshrc containing just a comment.
That will prevent this function being run again.
(1) Continue to the main menu.
(2) Populate your ~/.zshrc with the configuration recommended
by the system administrator and exit (you will need to edit
the file by hand, if so desired).
--- Type one of the keys in parentheses ---
I usually hit (2)
since the defaults are a good starting point, and any customizations I may want, I
would do after the installation, anyway. Yyou can choose (1)
and configure things at this point, however,
if you really feel like it and know what you are doing.
Install oh-my-zsh:
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Once oh-my-zsh is installed, we need to configure it, which is done via ~/.zshrc
file.
The plugins I usually enable are:
plugins=(git python pip pyenv aws command-not-found docker-compose docker kubectl dirhistory)
You should also re-source .zshrc configuration with source ~/.zshrc
once you make that change.
But equally importantly, to get everything looking and acting the way I like it, I also install a very popular zsh theme called PowerLevel10K by running:
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
and change ZSH_THEME to ZSH_THEME="powerlevel10k/powerlevel10k"
in ~/.zshrc
and re-source zsh by running
source ~/.zshrc
. The PowerLevel10K theme is extremely configurable, and the first time you run it, configuration
wizard will run, which will allow you to fine-tune many aspects of the theme.
3. Tmux For The Win
Tmux is a fantastic terminal multiplexer that allows you to run things on the server in tmux session, detach from the session, without interrupting those processes or a need to move them to background jobs. It also has great support for creating and managing multiple screen panes, allowing you to be very productive. Getting proficient in tmux takes a little bit of practice, but it is well worth it. I will share some configuration and most convenient non-obvious commands I use.
To make most of tmux, I use tmux plugin manager (tpm) and install some super-convenient plugins. To install tpm:
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
And my overall ~/.tmux.conf
looks like the following:
unbind C-b
set -g prefix C-o
# split panes using h and v
bind h split-window -h
bind v split-window -v
unbind '"'
unbind %
unbind r
bind r source-file ~/.tmux.conf
set -g mouse on
set -g default-terminal screen-256color
unbind r
bind r source-file ~/.tmux.conf
set-environment -g PATH "/usr/local/bin:/bin:/usr/bin"
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'dracula/tmux'
set -g @dracula-show-powerline true
set -g @dracula-plugins "network cpu-usage ram-usage"
run '~/.tmux/plugins/tpm/tpm'
Most Tmux keybaord commands start with a tmux “bind key”, by default Ctrl-B, then followed by other key combos.
My configuration, among other things, re-maps tmux command from Ctrl-B
to a much more convenient (in my
opinion) Ctrl-O
. In the rest of this post, I assume you have the same re-mapping. I also map creating
horizontally-split new pane to C-b h
and vertically-split one to C-b v
, which are way easier for me to remember
than the default combinations or other alternatives.
Toward the end of the config file, I enable “Dracula” theme for tmux, which I think is gorgeous, make Dracula’s prompt display current network connection, CPU and memory utilizations, adding extra coolness and utility to the whole thing.
You need to run tmux source ~/.tmux.conf
from a tmux session, after you change tmux configuration
Finally, to have tmux run all necessary plugins, please issue commands Ctrl-O Shift-i
. Again this assume
you also re-mapped tmux prefix to Ctrl-O
, from the default Ctrl-B
. In response, you should get
the output:
TMUX environment reloaded.
Done, press ESCAPE to continue.
Common, very useful key shortcuts for Tmux
Since various people choose to use different “bind key” (default is C-b
, but I like
C-o and some others like
C-a`),
in the following examples we will just refer to
the key combo as “bind-key”, but the default is Ctrl-b and in my config it is Ctrl-o. Also all of these
shortcuts assume my configuration, and not defaults:
tmux new -s sessionname
- create new sessionbind-key d
- detach from tmux session. Do not useexit
or the session will shut down!tmux a
- attach to the latest tmux sessionbind-key z
- toggle maximizing a pane and returning it to the original sizebind-key spacebar
- toggle between various useful preset pane layoutsbind-key o
- swap content in panesbind-key arrowkeys
- switch focus between panesbind-key q
- show pane numbersbind-key q #
- switch to specific pane number where # stands for 0,1,2,3…bind-key w
- preview session and windowbind-key x
- kill the active panebind-key ?
- see all shortcuts, if you forget any!
4. Emacs, With a Twist.
Installing emacs is fairly simple:
> sudo apt-get install emacs
> emacs --version │
GNU Emacs 27.1
Once emacs is installed, however, we want to run it in daemon mode (as a server) so that each launch of an editor is just client connecting to the server. This will make emacs launches significantly faster, and will also help with some aspects of retaining session between edits.
Let’s create the emacs daemon configuration file at .config/systemd/user/emacs.service
with > mkdir -p .config/systemd/user/
and vi .config/systemd/user/emacs.service
,
that has following content:
[Unit]
Description=Emacs text editor
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure
[Install]
WantedBy=default.target
Try launching it with systemctl start --user emacs
and stopping it with
systemctl stop --user emacs
I usually also have an emacs-reload
script on a path with the following content:
#!/usr/bin/env sh
systemctl stop --user emacs && systemctl start --user emacs
Once we have the daemon running, I usually create an alias for a client script and put it in my ~/.zprofile, which is startup/login script for zsh:
export TERM="xterm-256color"
export PATH="$HOME/bin:$PATH"
export PATH="$HOME/.emacs.d/bin:$PATH"
alias em="emacsclient -c"
To make emacs extra user-friendly for long-time vim users, like myself, make it minimalistically good-looking by modern code editor standards, provide a wealth of extensions and to use sensible defaults, I like to use Doom Emacs configuration framework.
To install Doom Emacs, run:
> # prerequisites:
> sudo apt-get install ripgrep
> sudo apt-get install fd-find
> git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.emacs.d
> ~/.emacs.d/bin/doom install
Installing Doom Emacs!
✓ Created ~/.doom.d/
- Creating ~/.doom.d/init.el
✓ Done!
- Creating ~/.doom.d/packages.el
✓ Done!
Generate an envvar file? (see `doom help env` for details) (y or n) y
> Generating envvars file
✓ Generated ~/.emacs.d/.local/env
... full printout skipped for brevity ...
✓ Finished! Doom is ready to go!
But before you doom yourself, here are some things you should know:
1. Don't forget to run 'doom sync', then restart Emacs, after modifying
~/.doom.d/init.el or ~/.doom.d/packages.el.
This command ensures needed packages are installed, orphaned packages are
removed, and your autoloads/cache files are up to date. When in doubt, run
'doom sync'!
2. If something goes wrong, run `doom doctor`. It diagnoses common issues with
your environment and setup, and may offer clues about what is wrong.
3. Use 'doom upgrade' to update Doom. Doing it any other way will require
additional steps. Run 'doom help upgrade' to understand those extra steps.
4. Access Doom's documentation from within Emacs via 'SPC h d h' or 'C-h d h'
(or 'M-x doom/help')
Have fun!
Once Doom Emacs is installed, spend some time with ~/.doom.d/init.el
and enable
the packages/extensions you like. One package I always enable is tree-sitter, which
is generic language parser/highlighter, and I put the following configuration
at the bottom of ~/.doom.d/packages.el
(package! tree-sitter)
(package! tree-sitter-langs)
and the following at the end of ~/.doom.d/config.el
:
(use-package! tree-sitter
:config
(require 'tree-sitter-langs)
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))
When emacs is installed, you should sync doom with doom sync
and restart emacs service,
otherwise the daemon/server won’t pick changes up. If you created the shell script above,
then you can do it simply by running emacs-reload
.
Enjoy, and let me know in the comments if you have further tips and tricks for making your Ubuntu environment minimalistically awesome.