How I sync my config files with Stow
An organisational nightmare
I have one machine for work, one machine for personal stuff and a bunch of servers for projects and school work. As I hop in and out of these separate computing systems, it gets pretty difficult to synchronise all my config files, settings, scripts and shortcuts.
1As this is a common problem that plagues many programmers, it is unsurprising that there is a clever piece of software written to solve this problem - Stow. Stow is a symlink manager that when coupled with any version control software (ie. git) can create a simple and effective config sync system. I have used such a system for the last couple of months and is something I can no longer live without.
When you’ve written the same code 3 times, write a function
— David Robinson (@drob) November 9, 2017
When you’ve given the same in-person advice 3 times, write a blog post
I find myself bringing up Stow pretty often in conversations so I wanted to take @drob’s advice. However, as there are many excellent blogs that already do a great job explaining what Stow is, I think I can’t add much value to that conversation. Instead, I’m going to shift my energy toward creating a straightforward how-to recipe.
The Big Picture
Here is the big picture of how a Stow-enabled config synchronisation system is set up.
You will need a
dotfiles
version-controlled repository. The simplest approach here would be to create a Github repositoryIn
dotfiles
, you will create separate folders for each application’s config file you wish to keep in sync. What you name these folders is totally up to you, but conventionally most people name the folder after the application
For example, a simple dotfiles
repo might look like this.
Here, I intend to sync my shell aliases, terminal configs (Kitty) and editor configs (NeoVim), so I create a separate folder for each.
Within each folder, you can create the config files that we want to be kept in-sync
Using Stow, you can then create a symlink of these config files which would be placed in the right locations on your file system for the respective applications to read from
Once this is set up, the day-to-day usage of this system is incredibly simple. Any time you make make edits to your config files on 1 machine, you simply need to commit and push the changes made in your
dotfiles
repo. Your config files are symlink-ed to the files in yourdotfiles
repo, and any edit you make will be updated. Next time you hop into a different machine, just pull down the latest changes in thedotfiles
repo and all your configs will be updated
Steps 3 and 4 are the tricky bits and I provide a more detailed example of them below.
Syncing a config file for the 1st time
Here is an example scenario. I have 2 machines (A and B), and I want to sync the configurations for the terminal application, e.g. the Kitty terminal. To configure this terminal, you would edit a config file kitty.conf
whose default location is ~/.config/kitty/kitty.conf
. Here is what you would do:
Yes, I see the irony in using Kitty because it is a GPU-accelerated application whose primary function is to print out text…
We start from machine A. Firstly, you will need to delete the existing
kitty.conf
fileIn your
dotfiles
repo, within thekitty
folder, create a newkitty.conf
file but make sure this file is in the same folder structure of the default config location. I.e. your new config file should sit in thedotfiles
repo like this
Fill up
kitty.conf
with your desired settingsNavigate back up to the
dotfiles
repo and runstow kitty
. This command will create a symlink of the contents of the kitty folder, which will create akitty.conf
in the~/.config/kitty/kitty.conf
locationWe are done setting up on Machine A. Commit and push the changes to your
dotfiles
repoFinally, log into Machine B. Pull down the changes and because we have not run stow in this machine, you will need to run
stow kitty
here too to create the symlinks.
Stow is something you only need to run the 1st time you add a config file. You do not have to run stow
for any subsequent edits.
Limitations
This config sync system is pretty sweet but it is not without some limitations. Here is a couple for you to be aware of.
Stowing too many config files can also get out of hand pretty quickly. You probably want to consider which applications you are genuinely using often enough across multiple machines, just so you avoid creating obsolete symlinks.
Additionally, there are some situations where you do not want config files synced. For example, I do not use this system to sync my shell configs because my shell configs might contain sensitive environment variables or have settings unique to the type of hardware the software is running on.
Appendix
─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.3.1 (2023-06-16)
os macOS Ventura 13.5
system x86_64, darwin20
ui X11
language (EN)
collate en_US.UTF-8
ctype en_US.UTF-8
tz Asia/Singapore
date 2023-08-10
pandoc 3.1.6 @ /usr/local/bin/ (via rmarkdown)
quarto 1.3.433
─ Packages ───────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
sessioninfo * 1.2.2 2021-12-06 [1] CRAN (R 4.3.0)
[1] /Users/ddanieltan/Code/ddanieltan.com/renv/library/R-4.3/x86_64-apple-darwin20
[2] /Users/ddanieltan/Library/Caches/org.R-project.R/R/renv/sandbox/R-4.3/x86_64-apple-darwin20/84ba8b13
──────────────────────────────────────────────────────────────────────────────
Study hard what interests you the most in the most undisciplined, irreverent and original manner possible – Richard Feynman
Reuse
Citation
@online{tan2022,
author = {Tan, Daniel},
title = {How {I} Sync My Config Files with {Stow}},
date = {2022-08-27},
url = {https://www.ddanieltan.com/posts/stow},
langid = {en}
}