Managing Dotfiles with a Makefile
Assumed Knowledge: make, GPG, git.
You can manage dotfiles with nothing but make and standard tools.
- Copy standard configs.
- Track changes with
git. - Keep separate branches for each computer.
- Securely handle secret files with GPG.
- Manage crontab.
The Setup
Mine looks like this:
1config/:
2 aerc cava khard rofi tut picom.conf
3 alacritty cmus lf s vdirsyncer powerbash.sh
4 amfora dunst ncmpcpp sc-im waybar powerbashrc
5 bat gtk-3.0 newsraft sway zathura redshift.conf
6 bottom himalaya procps systemd compton.conf
7 bugwarrior i3 profanity task mpd.conf
8 calcurse i3blocks qutebrowser tspreed mpv.conf
9
10home/:
11 gnupg mozilla vim bash_profile gitconfig inputrc xinitrc
12 local unison w3m bashrc gitignore_global tmux.conf Xresources
Hard Links
Standard configs are made with hard links, which means these two files are the same file:
dotfiles/home/bashrc.bashrc
Once you edit ~/.bashrc, that also changes dotfiles/home/bashrc.
A make pattern takes care of the path, so there's no need for dots in your dotfile manager.
1$HOME/.%: home/%
2 ln -f $< $@
Command-Based Files
Some files are usually created through commands, like ~/.gitconfig.
These can change on different computers, as you add git lfs on one, or a credential helper on another.
So if you don't want to keep them in sync, you can just put the universal commands into a Makefile.
If your name ever changes, then all computers receive that change, but nothing will touch the strange git helpers installed on that old laptop.
1$(HOME)/.gitconfig: git.mk
2 git config --global user.name "$yerName"
3 ...
The same approach lets you manage secrets.
For example, you can set the secret token value in glab (the Gitlab CLI tool):
1git_token != pass gitlab-token
2glab config set token "$(git_token)" --host gitlab.com
Secrets Management
You can use pass to manage secrets with make.
For example, to keep ~/.config/aerc/accounts.conf as a secret file, just throw it into pass:
1cat ~/.config/aerc/accounts.conf | pass insert --echo config/aerc/accounts.conf
Add this file as a secret, and make a rule to create these secrets from all the files in ~/.password-store/:
1secrets += ${HOME}/.config/aerc/accounts.conf
2
3$(secrets): ${HOME}/.% : ${HOME}/.password-store/%.gpg
4 mkdir -p $(@D)
5 chmod 700 $(@D)
6 gpg --quiet --decrypt $< > $@
7 chmod 600 $@
Handling Crontab
Changes in different computers' crontab files can inflict a lot of merges.
Avoid this by just making each set of tasks its own file:
1echo '@daily import_events.sh "https://dmz.rs/events.ical"' > extra/cron/calendar
2echo '@hourly mbsync -a' > extra/cron/email
Combine the lot with cat, then import this into cron:
1cron.txt: $(wildcard extra/cron/*)
2 cat $^ > $@
3 crontab $@
Example Repo
You can find my basic setup here:
1ssh -p 2222 soft.dmz.rs -t mkdots
Or just clone the repo and see how it works:
1git clone ssh://soft.dmz.rs:2222/mkdots .dots
2cd .dots
3make -n