Scripting, scripting, and more scripting. I wish there were a better way, but there isn't. And it will forever be brittle, because operating systems change. With that said, here's what I do.<p>First, I keep a personal monorepo. It not only has all my dotfiles, but also my personal website, and binary tools I've written. A game changer for me was git submodules, which let me keep third party stuff up to date with a minimum of fuss. The only thing I keep in a separate repo is my password repository.<p>So the main script I use invokes a lot of other scripts in order. This is so I can just run one thing to update everything. The first thing it does is sync the monorepo and password repos. Then it runs my homebrew stow command, which is like GNU stow[1] but I have all the control I want over it because I wrote it in Ruby. This not only syncs my dotfiles but also copies all my homebrew bins over to where they're not only in $PATH, but /usr/local/bin so that they're in root's path as well.<p>Next is package management. I run Arch Linux and use pacdef[2] for lightweight declarative package management. If I install some random package, it will remove it at this step, unless I put it in one of my package lists that I keep in the monorepo. This tool will take any Arch Linux install with paru or yay and make it into mostly the system I use every day. It is the most brittle part of the process because, well, operating systems change.<p>Finally, to manage all the <i>other</i> package management tools out there, I use asdf.[3] My script installs all the plugins if they're not there, update them, then installs everything. Most asdf plugins support a 'default lib' config, which install a list of packages whenever you install a version of the tool. It's not the wholly declarative solution that pacdef is, but I may eventually write enough scripting to get it there.<p>It has to be this way because Linux is freedom, and with great freedom comes great amounts of time spent learning how it works. I used to try to keep a portable config across OSX, Windows WSL, and Linux, but that was really hard to maintain, and my life got way simpler when I decided no more OSX or Windows. It's kinda possible to do but it's a ton of work.<p>But the basic building blocks are, 1) dotfiles, 2) system packages, 3) secondary packages. Get those three scripted, and you're off to the races.<p>[1] <a href="https://www.gnu.org/software/stow/" rel="nofollow">https://www.gnu.org/software/stow/</a><p>[2] <a href="https://github.com/steven-omaha/pacdef" rel="nofollow">https://github.com/steven-omaha/pacdef</a><p>[3] <a href="https://asdf-vm.com/" rel="nofollow">https://asdf-vm.com/</a>