Chezmoi – Manage your dotfiles across multiple diverse machines, securely
chezmoi.io
chezmoi.io
> Ask HN: Can I see your scripts?[1]
I really like this[2] solution from /u/hoechst,
> Not really a script, but a `.ssh/config` to automatically deploy parts of my local cli environment to every server i connect to (if username and ip/hostname matches my rules).
> On first connect to a server, this sync all the dotfiles i want to a remote host and on subsequent connects, it updates the dotfiles.
> Idk if this is "special", but I haven't seen anyone else do this really and it beats for example ansible playbooks by being dead simple.
Match Host 192.168.123.*,another-example.org,*.example.com User myusername,myotherusername
ForwardAgent yes
PermitLocalCommand yes
LocalCommand rsync -L --exclude .netrwhist --exclude .git --exclude .config/iterm2/AppSupport/ --exclude .vim/bundle/youcompleteme/ -vRrlptze "ssh -o PermitLocalCommand=no" %d/./.screenrc %d/./.gitignore %d/./.bash_profile %d/./.ssh/git_ed25519.pub %d/./.ssh/authorized_keys %d/./.vimrc %d/./.zshrc %d/./.config/iterm2/ %d/./.vim/ %d/./bin/ %d/./.bash/ %r@%n:/home/%r
[1] https://news.ycombinator.com/item?id=32467957I don't think that deploying all my dotfiles to a remote server is smart. But there are a few things that could be deployed that would help with quality of life.
I think this is a great way of doing that.
- templating for any configuration file built-in
- support for password managers
- can download and unpack an archive, or clone a repo, and refresh it e.g. once a week
- run scripts when applying config changes (either once, or every time)
- can handle config files that are externally modified
- can keep the source dotfiles encrypted on disk, and only unlock them when applying changes to the local generated files
In my usage so far Chezmoi has replaced and is now responsible for:
- Vim plugins
- ZSH plugins
- Generate SSH and GPG keys per context when a new machine is set up
- Git configuration (with per-machine and per context GPG and SSH keys)
- Install software on FreeBSD/Linux/MacOS that I need, both from source and/or package managers
- Per machine customization (e.g. differences between 4 core and 8 cores, or 1 GB of RAM vs. 48 GB RAM, etc.)
- Per OS customization (e.g. differences between ZSH on Arch vs. MacOS)
- Per host customization (e.g. different Vim configs on workstations vs. servers)
As far as setting up a new machine goes, I install chezmoi and git manually, and then I run `chezmoi init {dotfiles-repo}`, and that takes care of (almost) everything else, for MacOS, FreeBSD, Debian, and Arch Linux, each with the specific customization I need for that specific distro and host, all generated from a single source of configuration files.
Key for me is that all variations of e.g. `.zshrc` is generated from a single `dot_zshrc_tmpl` file.
Chezmoi is a tool that deepens with use, and I am finding more uses for it as I continue to use it.
When symlinks or a bare Git repo becomes unwieldy, perhaps the platform itself has a native solution (nix, home-manager) or there is something else that does all of it (ansible, dhall) and that's cool. In other cases there is Chezmoi, which was easy to learn to use.
... Except getting used to `chezmoi edit ~/.vimrc` to make changes to a config file. That is some hefty muscle memory to overcome.
You can get away with doing stuff like package installation as well but anything more advanced on system-level and you probably want to keep/introduce configuration management for that.
Looking at said install script it's also pretty much just figuring out the host OS and architecture, downloading the corresponding binary, checking its integrity and copying it in place.
I didn't even notice the install link (which is in a menu on the side) and the text didn't indicate another installation option.
> $ sh -c "$(curl -fsLS https://chezmoi.io/get)" -- init --apply $GITHUB_USERNAME
That this is even suggested as an installation command means that they might as well strike "securely" from the tagline. For someone interested in security the foul odor that this line emits is enough to make me stop reading.
This command basically downloads and execute something. Yes, it requires you to trust the author but that's what you always need to do anyway alas you don't read and compile yourself anything you install on your computer.
Or did I miss something ?
(1) I have the server you're curling-into-bash. I write my server to check if it's piped into sh; if so, I instead pipe malicious statements.
(2) I have the server you're downloading from. I write the binary you're downloading so that it later executes malicious statements.
The "don't curl into sh" is worried about the former.
But, the latter seems a much more practical attack, that reading the script you curl is insufficient to protect you from.
It seems weird to mention (1) without at least mentioning (2).
I'm not saying that you should trust anything coming from anywhere, but you have no other choice than to trust the author of any software you run on your computer.
Even if the Chezmoi's author was a malicious guy, why would he hide something in the installation script when this script literally permanently installs a program on your computer.
Trust seems like such an arbitrary set of lines in the sand anyway.
Adding a repo to your OS and installing the package? Fine.
Same developer provides an install script? Absolutely not.
You have to trust somebody eventually, whether it be your HW manufacturer, OS developers, packagers, developers, etc. There's a lot of it blindly going on, but a script running as your user? Just can't.
It also requires you to trust that the underlying http server/dns record server infrastructure did not change between runs of the command.
And what form of distribution do you propose that is secure against that?
Note also that the URL is HTTPS.
I don't know. I always think this line smacks of paternalism. For instance, plenty of projects suggest for installation something like:
git clone https://github.com/twpayne/chezmoi/; cd chezmoi; make; sudo make install
Of course, "curl | bash" is not always preferable. Re: security, "curl | bash" may be preferable here given the superuser privileges, or the privileges required by dpkg upon install of a stray deb package. But is the implication one reads the makefile and the source code before installing when one git clones a repo, but doesn't when the instructions say pipe to bash?I also think many are afraid to admit FOSS packaging security is mostly smoke and mirrors. Sure, it's nice re: trusting a mirror. It's nice for keeping track of packages and dependencies. But its technical security story vs "curl | bash" would seem only marginally better/worse depending on the circumstances.
Because trust is the great problem. "curl | bash" may have a smell, but it's mostly the smell of the sewer we live in.
Another question one might/should ask is -- what is the cross platform alternative? If it's "Build 10 packages for everyone," I'm not sure how happy that will make anyone. Just specifically re: this tool, imagine wanting to use it everywhere, however, you have a Mac dev laptop and your servers are a mix of Linux/FreeBSD. How much easier is it just to say "I trust chezmoi (because I would have had to trust it anyway) and 'curl | bash' is secure enough?"
- https://www.atlassian.com/git/tutorials/dotfiles
- https://www.ackama.com/what-we-think/the-best-way-to-store-y...
It's basically a helper for a bare git repository plus some added features.
I'm still in doubt though, as git will work forever, "without" bugs, and be supported on any OS :-)
[1]: https://nixos.org
Main selling point of Chezmoi seems to be the "multiple diverse machines" part, which would mean multiple OSes and at least Linux/macOS/Windows.
All my work machines are set up using a single, parameterized Ansible playbook.
I copied some of it into an example repository to showcase the structure and left the playbook.yaml intact for reference. You can find it on: https://github.com/cybrox/ansible-setup-example
I don't want to claim that this structure is in any way better or worse than anything else, it's just one that works for me. There's a lot of discussion on how Ansible projects should be structured. This allows me to simply run `WORKSTATION=home DESKTOP=wayland ansible-playbook playbook.yaml` on a fresh Arch Linux install and everything is ready to go.
For maintaining the repository, I got used to changing things in there and deploying them instead of changing dotfiles directly. However, I do also deploy a bash script to copy all the files from the system back to the repo to catch dotfile edits I did hastily at 3am.
An example of dotfiles being deployed with this approach is roles/shell/tasks/zsh.yaml
I used to use bash scripts myself, however, I did transition to Ansible because I often ran into problems with replayability of scripts (running them multiple times).
Ansible (and other tools like it) handle stuff like "change a line in this config file to that" or "add this flag here when xyz" easily and you can run it as many times as you like.
Also, Ansible Galaxy offers a lot of roles ready-to-use such as docker setup or asdf version manager plugin management. Though a lot of it is often not that well maintained.
Unfortunately I still have to use Ansible for stuff that isn't my dotfiles, but the less Ansible, the better. It feels like whatever use cases I have for Ansible are weird and not what other people are doing, because everything I try to do is difficult and poorly documented. For example, when I try to spin up a machine running Alpine Linux using Ansible, I've encountered all sorts of strange bugs, some of which I've reported and are (being) fixed, but it boggles my mind that what I thought would be really basic stuff, like setting the hostname or the timezone, is buggy as heck.
Similar solution for packages and other settings, just a bunch of shell script doing stuff. I tried using Ansible in the past, but maintaining a rarely used tool with many updates was too much of a hassle. At the end, the simple solution is the best one, for me.
When all the words are sitting around at the end of the day, you got a few good ones making dinner, and maybe a clever contraction sitting on the couch, then you have little Idempotent, chewing on a fucking crayon in the corner with a finger in the light socket.
Especially in light of Microsoft et al perhaps not always playing nice here (see, e.g. youtube-dl)
Previously I used symlinks to dotfiles in Dropbox but I find git a better match for dotfiles.
I'd rather tell the tool to watch for changes in my local files. Yes, most of them are in .config, so no big change, but still...
Matter of habbit I guess.
[git]
autoCommit = true
autoPush = truefish, neovim, tmux, skhd are the most important ones. Can't live without them.
I have a lot more stuff synced but that's one use case I rarely see mentioned if at all.
I wind up reinstalling or using new laptop/desktops all the time and its very helpful to keep things in sync. I HATE getting off my work laptop that I just spent 8 hours deving on and getting on my personal laptop and missing things. And vice versa.