Dotfiles and stow 📥
This post is 100% GenAI-free. Read here why.
There are many things I did not get right when I started doing research – back in my days 2015, when the ROS distro was Indigo, Python was at 2.7 but the default choice for robotics was mediocre C++ code or, worse, Matlab scripts. There are still many things that I do not get right today, but that’s a wider topic.
There is however one habit I picked up from a Linux savvy friend fairly early in my career (beginning of 2018, looking at the git history) that I think helped me streamline something that I find incredible tedious: setting up a pc after a fresh Linux install.
tl;dr, I have a Github repo dotfiles
containing
- dotfiles (duh) (
.bashrc
,.vimrc
,.bash_aliases
and so on) - an installation script
setup.sh
that I keep updated as my needs change and Ubuntu versioning advances.
On a fresh install,
git clone https://github.com/mattiaracca/dotfiles
source dotfiles/setup.sh
and… I have my machine back.
Disclaimer: Depending on your background, what I just described may be… the norm. If that’s the case, this post is not for you, I’m afraid. It’s for robotics researchers who, by nature of the field, come from disparate backgrounds: computer science, computer/mechanical/electrical engineering… and psychology, social sciences, and design if you look at the Human-Robot Interaction community.
Why versioning dotfiles
First, what are dotfiles? Brutally copy-pasted from this blog post
Dotfiles are hidden configuration files on a Unix-based system that are hidden by default due to their unique prefix (.). These files store configurations, settings, and preferences for applications and tools, such as version control systems and editors. They make it easy for developers to create customized environments personalized to their workflows.
Your .bashrc
is a dotfile. The .config
folder in your home is a standard place where applications expect dotfiles.
Why a dotfiles repo? Because having all my dotfiles in one place let’s me
- avoid remembering or googling stuff like does this dotfile go in
.config/
or directly in~/
? or how to install zotero/zoom/dropbox/ros/texlive?. - have a growing library of custom commands and settings that I can just
git clone
It does make it hard for me to work on vanilla machines (e.g. computers of colleagues) because I don’t have my commands/aliases. But then again, that’s a pretty rare occasion.
Versioning dotfiles is not really arcane magic. What really does it for me is the use of stow
and having a setup.sh
.
Using stow to handle dotfiles
The idea comes from here and I’ll never be grateful enough. In short, you use the command stow
to symlink your dotfiles (now neatly versioned in your dotfiles
repo) where they are needed.
Let’s say I want the versioned ssh config
file to go where it usually sits at ~/.ssh/config
. In the repo root, I create a ssh
folder, with inside the same folder structure of ~/.ssh/config
(so a folder called .ssh
with inside the config
file).
From the repo root, I then stow ssh
and now the config
is correctly symlinked where needed. If you make changes inside the dotfiles folder, they are immediately applied (it’s a symlink). If you or something changes them in ~/.ssh/config
, you’ll see it with git status
, ready to be committed (or discarded).
Another example: .vimrc
sits in ~/
. In the repo, create a vim
folder, put inside your .vimrc
, stow vim
, done.
This is what the tree
command would give you from the root of the repo
dotfiles
├── ssh
│  └── .ssh
│  └── config
└── vim
└── .vimrc
Machine specific dotfiles
What if I have many machines and some settings are wrong/nonsensical/unnecessary for some machine?
In that case, what works for me is to create machine specific scripts like mylaptop.sh
and then have this at the end of my .bashrc
if [ -f ~/dotfiles/host_specific/$HOSTNAME.sh ]; then
source ~/dotfiles/host_specific/$HOSTNAME.sh
fi
Like that, I have machine-specific commands, env variables, and the like.
The setup.sh
The setup script builds on all of the above and provides an entrypoint on a fresh install. These are excerpts of mine, just to give you an idea of what I mean
echo -e "\n===== Fresh installation =====\n"
sudo apt update
sudo apt install stow
read -p 'stow bash files? [y/n]: ' answer
if [ "$answer" = "y" -o -z "$answer" ];then
rm ~/.bashrc
rm ~/.bash_logout
stow bash
fi
read -p 'Do you want vim? [y/n]: ' answer
if [ "$answer" = "y" -o -z "$answer" ];then
sudo apt install vim
stow vim
fi
It’s not just stowing. The script does things I always forget how to do, like, e.g. create a ssh key
read -p 'Create SSH key? [y/n]: ' answer
if [ "$answer" = "y" -o -z "$answer" ];then
ssh-keygen -t ed25519 -C "definitively@not_my.email" -f ~/.ssh/id_ed25519
ssh-add ~/.ssh/id_ed25519
fi
or install things that require more than a simple apt install
, like e.g. zoom
read -p 'Do you want Zoom? [y/n]: ' answer
if [ "$answer" = "y" -o -z "$answer" ];then
wget -O /tmp/zoom.deb https://zoom.us/client/latest/zoom_amd64.deb
sudo apt -f install /tmp/zoom.deb
(crontab -l ; echo "@reboot nohup setsid zoom")| crontab -
fi
The “secret” here is maintaining the script over time, adding new procedures to it (better when you are doing a procedure manually for the first time), removing stuff that became irrelevant or obsolete, etc.
I cannot estimate how much time this saved me (also because maintaining the repo does take some time every now and then). It sure improved my “Linux Hygiene” and made my actual work (doing research) much smoother.
(Dis)liked what you read?
Let me know! Drop me an email at mattia dot rh at gmail dot com with [BLOG] in the subject. Some other posts: