Published: 23.01.2021 | Edited: 23.01.2021 | Tags: dotfiles

Keep Gnome Shell settings in dotfiles with yadm

Gnome project went through a long and turbulent journey in a open-source world, filled with forks, pivotal changes and controversy. Gnome is based on GTK widget toolkit. Widget tookit is a software library used to build graphical user interface (GUI). GTK was born as a more open alternative to Qt, which at a time had a proprietary license. Qt is another widget toolkit powering the KDE desktop environment (DE). Desktop environment is a collection of software running on top of an operating system sharing a common GUI. Together, GTK and Qt are building blocks representing majority in the linux desktop environments. There are many more GTK based desktop environments besides Gnome. Gnome is however by far the most used in the wild.

Now that we have finish all the boring paperwork, let's get to the fun. Let me just share a little from my experince with you. Over my life I have tried many of the desktop environment, starting with the KDE on the now discontinued Mandriva Linux back in 2001. It was very compact, because I had it burned on the mini CD and I could cary it around wherever needed (USB sticks were not used to boot linux back then). Whenever there was a computer somehwere, It was running Windows 98, ME, 2000 or XP. All of them required the password to log in. Of course fathers would not share the passwords with us, the children. But the files were not encrypted, so to reach them one just needed to insert the CD, boot it and copy whatever was needed. Our most precious trophies from this highly nefarious activity was copying games. Obviously, you do not go over the lengty process of copying the game when you have only a limited time at the computher, when a father permits it. You want to play when you can. Copying can be done when fathers are still at work, having a password with them.

A funny thing was that the Mandriva booted from the CD had a k3b burning software bundled in, but most computers had only a single optical drive. I was 10 and I was really scared to take the CD out when a system was booted from it, until I first tried. We really wanted to play that Medal of Honor on the other computer. I was then really surprised that the system did not crash when I took the mini CD out to insert a blank CD to burn the game on it. Life is nice when you are a kid.

Fast forward today, I still love working on KDE ocassionaly, but currently I do too use Gnome as my daily driver. Having a strong sense of automating things, provisioning my system after a fresh install is one way how to express this trait. One of the ways to store settings of your desktop environment and programs running on it is to store so called dotfiles. Dotfiles a human readable configuration files stored in the home directory. The begin with the dot character, which makes them hidden, hence the name.

Dotfiles Manager

As with almost anything software, there are multiple ways to solve a problem. I feel like repeating this sentence too much, it holds true. In fact, I believe it is much better to know multiple ways to solve a problem, because it gives you the possibility to verify the validity of your solution solution.

One popular solution of managing the dotfiles is to use a bare repo. It is a very good solution many swear by, because it requires nothing else but git and git knowledge to make it work.

In fact the solution I am going to get it is exactly the same bare repo, but wrapped with a few enhancements. The package is called simply Yet Another Dotfiles Manager, yadm.

YADM also requires only git knowledge to get the most out of it, just replace the git command with yadm:

yadm init
yadm add <important file>
yadm commit

Let's take a look how to handle Gnome configuration files with yadm.

Accessing Gnome configuration

Anyone who builds software that wants it's configuration files to be modified by users makes sure the files are in the human redable format. Sadly, due to some unfortunate circumstances, this is not the case for Gnome dotfiles. They are not stored in the pre-defined location, ready to be edited. You have to first export, or more precisely dump them, before you can read and possibly store them with whatever technique you use to store your dofiles.

The word dump is used in the software world for a process of extracting all the information from a single reservoir, usually some sort of memory buffer. To make a dump of all Gnome settings, run command:

dconf dump / > gnome-settings.ini

I would argue that this is not dump in the original sense, because dconf is smart enought to only return non-default, which means modified values. You can also specify only a subset of the value, for instance /org/gnome/desktop instead of just /. We are interested in storing all the settings to easily load them on the freshly installed system, so sticking with /, a.k.a the root is preferred. For a completenes, here's how you apply the settings back into your system:

dconf load / < gnome-settings.ini

Naturally, to make yadm keep track of your setings, run the following:

dconf dump / > gnome-settings.ini
yadm add gnome-settings.ini
yadm commit

However, there is a problem with this approach. You have to do it before every dotfiles update manually. At this point the advanced features of yadm comes handy.

Git hooks

If you use git long enough, chances are you stubmled upon the feature called hooks. Hooks are not exclusive of git, in fact the term is commonly used to refer to an routine that is executed atuomatically when some circumstances are met. Git defines two prefixes for hooks: pre-* and post-* that execute before the given circumstance and after it, respectively. They can be conbined with some git command names to form a self-explainig hook names like pre-commit or post-merge.

One useful application of git hooks is automation. Once you set a certain hook up, you do not need to think about it. Our problem with Gnome settings is that it requires three manual steps to get your current Gnome settings into the dotfiles repository, where saved and accesible to other machines for cloning.

Why would I need some dotfiles manager's advanced features, when the git itself already provides this functionality, you might ask? Well it is certainly possible to do it without yadm or any other wrapper. It looks like your bare repo hook commands would require environmental variable called GIT_WORK_TREE. I did not try it, precisely because I could not find any good documentation on the search term git bare repo hook. Feel free to explore or document this yourself.

Yadm advanced features

Yadm on the other hand has the hooks feature as a first-class citizen. The yadm documentation differs from the git hooks documentation in the delimiter. While git uses dash after the prefix, yadm uses an underscore. To put this into perspective, in git you define pre-commit hook, while in yadm you spell it as pre_commit. This a caveat to keep in mind. If you find out it does not matter for either tool, please let me know.

To automate Gnome settings commit process, create the file ~/.config/yadm/hooks/pre_commit and don't forget to make it executable:

#!/bin/bash

dconfFile="$HOME/.config/dconf/settings.ini"

dconf dump / > "$dconfFile"
yadm add "$dconfFile"

You can provide a different dconfFile location according to your personal taste, but I like to keep it somehwere relevant where I do not see it. It is not like editing this file directly will help you in any way - it will get rewritten before every commit. Now change some Gnome settings manually, for instance some keyboard shortcuts and make a yadm commit:

yadm commit

You will see the settings file in staged chages:

# Changes to be committed:
#   modified:   .config/dconf/settings.ini

Nothing prevents you adding other files before commiting, if you have already added some, you can move all tracked into staged with

yadm add -u

A nice trick is to add this command into our pre_commit file, this way all the tracked files will staged automatically before every commit. This way, you can even run commit as a cron job, with your sole responsibility being adding or removing files into tracking! Feel free to steal thse two lines for yourself and put them into your ~/.config/yadm/hooks/pre_commit:

#!/bin/bash

dconf dump / > "$HOME/.config/dconf/settings.ini"
yadm add -u

Provisioning your system

Now that we have commiting sorted out, the only thing left to do is making sure that the setting will be loaded into the system when needed. For this, we make use of another yadm advanced feature called bootstrapping.

Bootstrapping is a fancy name for another executable script. When yamd clones your dotfiles into the fresh system and detects your bootstrap script, it asks you if you want to run it. That's it. To meet our goal, it has to load the Gnome settings back to the system during provisioning. The script resides at ~/.config/yadm/bootstrap:

#!/bin/bash

dconf load / < "$HOME/.config/dconf/settings.ini"

You can also put other commands here to suit your needs. Have fun!