__ __ _
| \/ | __ _ _ __ __ _ __ _(_)_ __ __ _
| |\/| |/ _` | '_ \ / _` |/ _` | | '_ \ / _` |
| | | | (_| | | | | (_| | (_| | | | | | (_| |
|_| |_|\__,_|_| |_|\__,_|\__, |_|_| |_|\__, |
|___/ |___/
____ _ __ _ _ _ _ _
| _ \ ___ | |_ / _(_) | ___ ___ __ _(_) |_| |__ __ _
| | | |/ _ \| __| |_| | |/ _ \/ __| \ \ /\ / / | __| '_ \ / _` |
| |_| | (_) | |_| _| | | __/\__ \ \ V V /| | |_| | | | | (_| |
|____/ \___/ \__|_| |_|_|\___||___/ \_/\_/ |_|\__|_| |_| \__,_|
__ __ _ __ _ _
| \/ | __ _| | _____ / _(_) | ___
| |\/| |/ _` | |/ / _ \ |_| | |/ _ \
| | | | (_| | < __/ _| | | __/
|_| |_|\__,_|_|\_\___|_| |_|_|\___|
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.
Mine looks like this:
config/:
ο aerc ο cava ο khard ο rofi ο tut ξ picom.conf
ο alacritty ο cmus ο lf ο s ο vdirsyncer ο powerbash.sh
ο amfora ο dunst ο ncmpcpp ο sc-im ο waybar ο powerbashrc
ο bat ο gtk-3.0 ο newsraft ο sway ο zathura ξ redshift.conf
ο bottom ο himalaya ο procps ο systemd ξ compton.conf
ο bugwarrior ο i3 ο profanity ο task ξ mpd.conf
ο calcurse ο i3blocks ο qutebrowser ο tspreed ξ mpv.conf
home/:
ο gnupg ο mozilla ξ« vim ο bash_profile ο gitconfig ξ inputrc ο xinitrc
ο 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.
$HOME/.%: home/%
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.
$(HOME)/.gitconfig: git.mk
git config --global user.name "$yerName"
...
The same approach lets you manage secrets. For example, you can set the secret token value in glab (the Gitlab CLI tool):
git_token != pass gitlab-token
glab 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:
cat ~/.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/:
secrets += ${HOME}/.config/aerc/accounts.conf
$(secrets): ${HOME}/.% : ${HOME}/.password-store/%.gpg
mkdir -p $(@D)
chmod 700 $(@D)
gpg --quiet --decrypt $< > $@
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:
echo '@daily import_events.sh "https://dmz.rs/events.ical"' > extra/cron/calendar
echo '@hourly mbsync -a' > extra/cron/email
Combine the lot with cat, then import this into cron:
cron.txt: $(wildcard extra/cron/*)
cat $^ > $@
crontab $@
You can find my basic setup here:
ssh -p 2222 soft.dmz.rs -t mkdots
Or just clone the repo and see how it works:
git clone ssh://soft.dmz.rs:2222/mkdots .dots
cd .dots
make -n