Claus Beerta

Managing "dotfiles", in the most convoluted way possible

For anyone who spends a significant amount of time on the command line, configuration is everything. Whether it’s a finely-tuned .bashrc, a well-organized .vimrc, or a bloated .tmux.conf, your dotfiles shape your workflow. But as you move between different machines, keeping these configurations in sync quickly becomes a hassle.

That’s where version-controlling your dotfiles with Git comes in.

By storing your dotfiles in a Git repository, you gain a powerful way to track changes, experiment with new configurations safely, and deploy a consistent development environment across all your systems.

Just putting your configuration files in git is too simple though, there has to be a way to make this complicated and convoluted, so combining it with Templating in Jinja, and running Systemd Services to trigger updates on Changes is a good start.

Structuring the Dotfiles repository #

For easier maintenance, i prefer to not use hidden directories and files in my dotfiles repository, hence my setup does not have them:

/home/claus/.dotfiles/
├── bashrc
├── bin/
├── config/
├── gitconfig
├── inputrc
├── kube/
├── local/
├── ssh/
├── tmux.conf
├── vimrc.j2

Deploying dotfiles to your $HOME #

First, just having the Configuration in git does not help, the files need to be installed into your $HOME for applications to pick them up.

A Simple shell script does the job, symlinking the configurations to their proper target. But We are not about simple.

As an avid Ansible User, and enjoyer of Jinja Templates, we should leverage it in our dotfiles. Configurations that are dependant on Variables and thus can differ from machine to machine are just the extra bit of spice we need.

Enter the Python Script that deploys Dotfiles, rendering them on the go.

Using Systemd to trigger on changes #

Now running the install-dotfiles.py script every time i change something in my vimrc or Hyperland Config gets old quick, so let’s leverage systemd to run the script for us. Systemd brings systemd.path.

Create a Service that runs the python Script as OneShot: dotfiles-render.service.

Now to trigger the Script, the Systemd Path is deployed

An Example for Hyprland #

Hyprland is my preferred Tiling WM these days, i have a few systems that do slightly different things.

bremusa for example is primarily a Kiosk style System mainly used to watch logs, and wallpapers, and starts wayvnc so it can be Controlled without Input Devices attached. So the Configuration is deployed dependent on the hostname the script is executed on:

alkaia and okyale are my main Desktops, hence the need for some Music Playing with ncmpcpp and some eyecandy with cava

exec-once = ~/.dotfiles/bin/swww-wallpaper.sh
{%- if hostname in ['bremusa', 'lysippe'] %}
exec-once = wayvnc
{%- endif %}

exec-once = $terminal -a btm btm
{%- if hostname in ['bremusa'] %}
exec-once = $terminal -a logs.sh ~/.dotfiles/bin/logs.sh
{%- elif hostname in ['alkaia', 'okyale'] %}
exec-once = $terminal -a cava cava
exec-once = $terminal -a ncmpcpp ncmpcpp
{%- endif %}

A Bash Function to commit/pull/push #

For quick git commands, to not have to change into the dotfiles directory every time, i’ve been using a little function in my bashrc:

dotfiles() {(
  pushd $HOME/.dotfiles || exit

  if [ -z $1 ] ; then
    git status -s
  else
    git "$@"
  fi

  ~/.dotfiles/bin/install-dotfiles.py
  popd || exit
)}