5 Principles for Your dotfiles Repository

Like many developers, I’ve long kept a git repository containing my “dotfiles.” These files configure a UNIX system to my liking and are useful for setting up a new computer or remote environment. After a long time with my previous dotfiles repository, I recently had reason to change my setup. Here I’ll share five lessons I’ve learned.

The catalyst for my recent revamp of my dotfiles repository was actually VS Code. More specifically, the Remote – Containers extension for VS Code. This extension is excellent for reasons I won’t go into here, except for one: it provides a convenient and reliable feature for automatically applying your dotfiles to the new containers it spins up. There is a catch. It expects your dotfiles to be publicly accessible on GitHub.

Naturally, the principles I list here are influenced by this, but I think they stand on their own as well.

1. Dependencies are a liability.

Many application developers aren’t comfortable with shell script, as it’s not something we regularly have to use. It’s true that shell script appears a little arcane and suffers some unfortunate default decisions about error handling.

Therefore it’s pretty common to reach for a more familiar programming language when you write the script that installs your configuration files into their proper destinations. I have done it as well.

Unfortunately, the point of your dotfiles is to configure an unfamiliar system that may vary significantly from your own. External dependencies are a liability here, as they are just one more obstacle on your way to a comfortable and familiar working environment.

This problem compounds when using Remote Containers, as your dotfiles setup script will be run automatically just after the container is created. Any external dependency will probably just lead to breakage.

So, it’s best to just go ahead and write some shell script. It’s not so hard and will serve as a useful counter-pressure against any urge to over-engineer what should be very simple.

2. Make your dotfiles repository publicly accessible.

Okay, this lesson is somewhat forced upon you if you intend to use Remote Containers. Regardless, I still think it’s a sensible approach.

When pair programming with other developers, it’s not uncommon to end up discussing your environments and learn new things from each other. Having your repository publicly accessible makes it easy to share a reference to your own setup with others who may be curious.

3. Don’t store secrets in your dotfiles repository.

This naturally follows as a consequence of making your dotfiles repository publicly accessible, but it’s worth noting that I view this as desirable in its own right.

Fundamentally, these are two different things:

  • Trusting an environment enough to accomplish some work in it
  • Trusting an environment enough to bestow it with your private keys and secrets

Rather than conflate the two, it’s best to acknowledge that your dotfiles solve a need pertaining to the former. When you trust a system enough and have cause to store your SSH keys, etc, then it’s time for a different tool. Personally, I have a shell script in my dotfiles repository that will give my private SSH keys to another machine. It must be run manually from a system that already has the keys, and I haven’t found the need to add anything else.
Finally, be careful when you symlink directories. If you symlink your dotfiles/ssh directory to ~/.ssh, you’ve created an accident waiting to happen. For this reason, I just manually link a few specific files.

4. Sometimes a symlink isn’t the answer.

Sometimes you may want to customize some aspects of a tool, but not all. My personal example is I sometimes set git includeif directives specific to certain file paths on a certain machine. This configuration is, by its nature, not portable to different machines. Yet I still want my other git configuration to apply from my dotfiles.

To solve this, I simply have my dotfiles install script apply my desired git configuration via a series of git config --global ... ... commands.

5. Don’t rely on an interactive terminal.

This last principle is most consequential if you intend for your dotfiles to be compatible with the Remote Container extension for VS Code.

When the extension installs your dotfiles into a newly built container, it does so without the use of an interactive terminal capable of reading text. If your dotfiles installer has any prompts, it will fail.

Make your dotfiles repository more useful.

Following these rules has made me much happier with both my dotfiles setup and VS Code’s Remote Containers extension. I hope this list has provided some useful insights for you.