Hacker News new | past | comments | ask | show | jobs | submit login
Managing Dotfiles with GNU Stow (2016) (alexpearce.me)
170 points by harporoeder on May 13, 2021 | hide | past | favorite | 66 comments



(2016)

> GitHub even has a website dedicated to different ways of organising and deploying them <https://dotfiles.github.com/>.

404, I presume https://dotfiles.github.io is what they were referring to, which is not affiliated with GitHub at all. (And there you see one of the reasons for shifting user content away from *.github.com to a different domain.)

----

This submission is presumably inspired by a current/recent discussion at https://news.ycombinator.com/item?id=27134249 on A Way To Manage Dotfiles, https://github.com/kalkayan/dotfiles, which is predicated upon another approach: using a bare Git repository with its work tree as the root of $HOME.


It's just a very old link from before github.io existed for Github Pages: https://github.blog/2013-04-05-new-github-pages-domain-githu...


Is possible they meant that to mean a website on GitHub, and not an actual GitHub website.


I've tried using a number of these solutions but I always have the same problem which is that after a while not using it regularly I'd want to make a change and forget the magic incantations, get frustrated and stop bothering.

To be fair I also have this problem a lot administering my linux machines because they just work - until they don't. Then I have to re-learn what to do to fix the problem.


Having had the same problem I ended up with this nice setup https://www.atlassian.com/git/tutorials/dotfiles which is rooted in a post by HN's StreakyCobra https://news.ycombinator.com/item?id=11071754

It has served me well for a few years now


I use a very simple Makefile to install and remove my dotfiles. If you want to add a new one it's simply a case of creating a directory and adding your config file to it and running `make up` (with `down` to remove)

You can change any of the files by accessing them via your .dotfiles directory or in their normal place - they're just symlinks.

https://github.com/peteryates/dotfiles


Yea I'm pretty sure I have a dotfile tool I haven't used for a few years.

Between hourly snapshots and maintaining the same install for many years across many machines its all kind of a waste of time to me.

It's way easier for me to clone a drive or restore from backups than fuck about trying to reinstall everything how I like it.

I haven't installed Linux for years. Is it easier than dd yet?

I guess maybe if you use multiple Mac's or something it's an issue?


Write a setup script with comments?


I cut out the middleman and just wrote a script that copy-pastes all my config files into a git repo, and another one that copies them back. I'm sure there are better ways but this is just a list of `cp -r` commands, so no matter how tired I am that day it's dead simple to extend.


I've tried this and a lot of other dotfile managers (homesick, homeshick, etc), my current favorite and what I'm using now is YADM:

https://yadm.io/


The issue I have with yadm is that, unlike stow, it can't manage directories.

For example, if you want to keep track of your whole Firefox profile's directory (without bothering adding/committing single files), in stow it's as simple as symlinking ~/.mozilla/firefox/<profile_dir>.

For programs whose configuration you know intimately this is not a problem (e.g. for bash, we all know we probably just need .bashrc), but not all programs rely on a single flat configuration file.


What’s nice about Yadm is that the mental model is so simple that it’s impossible to forget—just a Git repo with worktree in ~.


I don't understand this - why not just store them in git directly?

I have a git project called .linux-env. I can just clone it on any machine and ln my ~/.bashrc/~/.profile to it. Even works on mac.


It has a lot of additional features that a plain git repo won't provide, such as alternate files based on OS type, hostname etc: https://yadm.io/docs/alternates#


that's literally just an if-statement in your bashrc

    unamestr=`uname`
    if [[ "$unamestr" == 'Linux' ]]; then
        source ~/.my_environment/bash/linux/.bashrc
    else
        source ~/.my_environment/bash/osx/.bashrc
    fi
etc.


Why would I want to bother with that when I can just use the software above to simplify that for me, in addition to a bunch of other features it offers?


YADM is great. Was suprised I had to scroll this deep to before it was mentioned.


Thank you for sharing this, I just adopted it.


Same.


If I had the opportunity I always thought it would be fun to learn and then modify the Linux kernel so that file lookups to ~/.* get redirected to ~/config/.* and I could finally have a clean home directory.


You might try convincing projects to adopt the XDG spec[1] instead, might be easier.

Might be.

I've been trying something similar using Apple's framework bundle layout[2] and using XDG to point config files to ~/Library/ApplicationSupport etc, but programmers know better! Just spray whatever files you need into my home dir, developers, be my guest…

[1] https://specifications.freedesktop.org/basedir-spec/latest/a...

[2] https://developer.apple.com/library/archive/documentation/Ma...


Best way to make dev do that is to make it easy for them.

E.G: I used to "spray my files in the home dir" for my apps, until I discovered "appdirs" (https://pypi.org/project/appdirs/1.4.0/). Once I had an easy way to always has a clean and correct path for my app config/data/tmp file, I just used it.


Depending on how things are linked it might be simpler than you imagine and not involve any kernel modifications, you can do a lot of cool and/or horrifying stuff with a few environment variables: https://unix.stackexchange.com/questions/24811/changing-link...

If anything this would discourage more programs from adopting the xdg spec though.


I gave in trying to control the home directory long ago, it's a complete free for all, there has to be at least a dozen common and different ways programs decide to store configuration and caches etc.

I install my dotfiles globally into the system for the programs I care about with a simple shell script. Our desktops/laptops are usually all single user these days anyway, I don't see the point in trying to constrain things to a home directory. The nice things about this is that I can nuke my home directory when I feel like it, this is especially useful for programs I just want to reset without figuring out where they've littered all their configs... obviously you need to keep the dotfile repo outside of the home directory for that.


> I gave in trying to control the home directory long ago, it's a complete free for all, there has to be at least a dozen common and different ways programs decide to store configuration and caches etc.

This and the security free-for-all that programs enjoy come from a simpler, more naive time in personal computing. Personally, I think one of the few things mobile OSs get right[0] is the idea that applications cannot be trusted to behave and the default should be to keep them in their own little sandbox until the user says otherwise. Launch them in their own namespace with only the things you want them to have access to mapped in or redirected as per your preference.

[0] I have issues with the implementation, but the idea is sound.


There is different ways people have done it but there is only one standard.

Make issues on GitHub and hope for the best. Most of the time it's already a "I don't care, won't fix".

Apparently people just don't care that I have .cache mapped to a tmpfs and they don't care that their cache stored in .config or .shitappdevelopersinc is thrashing my remote backups.


You may try cgroups and mount namespaces with bind mounts. Alternativelly you can wrap apps in Snaps[0] yourself, or use some other app packaging/isolation concept.

[0] https://ubuntu.com/blog/apps-to-snaps


Tried snaps on a top performance notebook. No single app was responsive when e.g. pressing right mouse button. It's just not usable, sorry.


I think FUSE would be enough.


LD_PRELOAD is what you want.


This would not work for statically linked software.


Nix plus homemanager plus direnv is the best solution I have found so far. Managing config (dotfiles) is only one part of the problem. You usually also need some way to install applications/tools ideally in a specific version. your config might not work as expected with a different version and you would have to remember what exactly you installed. As a developer using direnv will even allow you to use different versions of tools for different projects/ directories


I see a lot of people talk about homemanager, but I've been happy enough with the following in my configuration.nix:

    system.activationScripts = {
      dotfiles = ''
        cd /home/chriswarbo/.dotfiles || exit 1
        for X in *
        do
          [[ -h "/home/chriswarbo/.$X" ]] && continue
          [[ -e "/home/chriswarbo/.$X" ]] && {
            echo "WARNING: Found ~/.$X but it's not a symlink" 1>&2
            continue
          }
          (cd /home/chriswarbo && ln -s .dotfiles/"$X" ."$X")
        done
      '';
    };
I've been using NixOS for many years, but my dotfiles repo goes back even further ;)


For me, one plus of home-manager is that I can easily use it and share modules between NixOS and, say, Alpine + Nix


direnv is one of those things I've never found a use for because it's so simple to roll your own and because there are invariably situations I have that they don't handle well, my work needs don't map well to a directory based approach for example. My home implementation that's evolved over the years is about 60 lines of bash but a simple bare bones (and unsafe) one is as easy as:

  function cd { builtin cd "${@}"; [[ -f "$PWD/.env" ]] && source "$PWD/.env"; }
To me stow seems similar, I see little to no advantage over a script/makefile that creates the symlinks and you have the complexity of another tool to learn.


Can you describe more your setup? Some repo?


Heres home-manager repo you could try to learn from: https://simatime.com/git/ben/cfg.git/


I just make my home directory be a git repo directly. That's even simpler -- no symlinks. You have to get used to having a repo with many unchecked-in files, but it works well enough. I have a git alias or two to help. This has been a good solution for me for more than a decade across ~a dozen OS installations.


I've seen a few people doing this, but I also frequently run `git clean -xffd` in my actual source code directories to clean them, so I'd be deathly scared of accidentally running it in the wrong directory and wiping out half my homedir.


alias config="/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME -c status.showUntrackedFiles=no -c submodule.recurse=true -c alias.update="'"!bash '"$HOME"'/.config/dotfiles/update_dotfiles.sh"'


You misunderstand. I'm talking about intending to run `git clean -xffd` under `~/src/some-project` (a git repo for some code) but accidentally running it under some other directory, such that it ends up running against `~`

Making aliases for working with `~`'s repo doesn't prevent that.


Yes it does. I do the same, with an alias and have .git somewhere else not directly in $HOME, but pointing to it with --git-dir. If you run git in ~, it will not recognize it as a git repository or worktree. You can only modify the repo with the alias or by specifying --git-dir explicitly.

These setup also prevents zsh/bash git prompt extensions from detecting git the the home folder repo, which can be confusing, I think.


Oh, I missed the `--git-dir` part. My bad.


Snapshots to the rescue


I do the same. It may benefit you to add "*" to .gitignore, as I describe here:

https://news.ycombinator.com/item?id=25564558


This is exactly what I do too. No messing with magic aliases to tweak --git-dir and --work-tree, just vanilla git.


https://www.electricmonk.nl/log/2015/06/22/keep-your-home-di... has been working nicely for me on multiple computers.


^ This is the best solution I've found (detached head). Add a single cron line to automatically commit and push changes and you get automatic backup of dotfile changes. The only thing missing now is for pass to handle files as secrets.


Nested git repositories can cause problems which you may want to watch out for.


I use GNU Stow to manage my dotfiles and it's awesome because with Stow and Brew, I could create a script that setup everything in my machine from scratch, with one command. If anyone wants to take a look, it's here: https://GitHub.com/diegoholiveira/dotfiles


NixOS would probably suit you well then, the "installer" even generates the initial config file you to use for build your machine.


100% nix with home manager, throw it into a repo and I'm done. Use across several machines. It's a dream

https://github.com/NelsonJeppesen/nix-lifestyle


I'll take a look. Thanks :)


Whenever I install a new distro, I never format /home partition. Also, I rename my home directory to <username>_old and create a new one. I start with mv of the most common files/directories like .bashrc/.mozilla etc and gradually move more as I need. This way after 2-3 months, I've left the old/unused cruft behind and can remove the _old home directory (in practice I keep them around because the size is small since I keep most of my documents in a separate partition and just symlink to that). If I'm changing computers, I restore the home from daily backup, rename it to _old and do the same thing.


I don’t do it as neatly, but I something similar when upgrading to a new macOS version every couple of years: I install it on a new volume and then move everything over gradually. The previous, still bootable volume will exist until I need space.


> But, as you can imagine, manually linking dotfiles quickly becomes laborious and error-prone. One solution is to create a script that links the files for you, but I think there’s a better way.

Yeah I have no issues doing this. I can count on any machine having bash and git, and I don't have to relearn how the tool works every few months.


It’s not an either/or :) I use a bash script which invokes stow.

The good: it’s a little easier that way because stow handles edge cases (e.g. existing symlink) in a sane way.

The bad: it’s annoying because stow has to be installed and it refuses to descend into subdirs. So, for example, if you want to stow type/desktop, you have to cd into type first.

Basically it could be better... but it used to be worse.


I think that in this case like in many others, the more the tool approximates the behavior of something you already know, the easier it is to use. I don't want to lose time learning yet another tool just for syncing 7 dotfiles from a machine to another.

I've been going with `vcsh`[1] for 2 years now -- essentially a wrapper git that works with a home directory git repo without all the annoyances. To be fair I don't even exactly knows how it works (which may be a testament to how nicely it is done). It's just basic git commands and it doesn't create a .git in your home folder.

As simple as : $ vcsh {name_of_repo} status # check changed files $ vcsh {name_of_repo} add .. $ vcsh {name_of_repo} commit .. $ vcsh {name_of_repo} pull .. $ vcsh {name_of_repo} push ..

[1]: https://github.com/RichiH/vcsh


chezmoi seems really promising. Been planning on migrating my dotfiles to it soon:

https://www.chezmoi.io/


You should! I switched from stow to chezmoi in the last year or so. Chezmoi is definitely an upgrade.


More dotfiles stuff on the vcs-home wiki:

https://vcs-home.branchable.com/


I used stow for a few years, but I outgrew stow when dealing with different architectures (arm vs x86_64) and OS (macOS, Debian based, RHEL based).

I settled upon chezmoi and don't have any complaints aside from it being a little bit cumbersome when merging (mostly due to my inexperience)

https://github.com/twpayne/chezmoi


I did a CTRL + F for “docker” and “container” and surprisingly didn’t see any hits in the first page of comments.

I’ve found it’s a lot easier to just make a single docker image of my favorite OS, load it with my dotfiles, vim plugins, etc. and then pull it down wherever I am.

Of course, this means you need Docker running on the machine. I’ve hit a couple of snags with credentials and key files, but I just end up mounting them as a volume or environment variable.

I followed this guide I found on HN, and it’s worked incredibly well.

https://news.ycombinator.com/item?id=26669474


Why not store everything in a Git repo, and symlink the dotfiles to the right place?


All the tool does is make that easier. It does exactly that.


I manage them and stuff installed manually with https://zolk3ri.name/cgit/zpkg/.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: