I had an M1 MacBook Pro I’d been living in for years, and an M4 Pro Mac mini I kept not buying. Every time I got excited about the upgrade — more RAM, more machine — I’d remember what comes after the unboxing: porting my entire life onto it. And I’d close the tab.
The annoying part is I didn’t even want my stuff moved over. I wanted the opposite — a clean slate, none of the bloat you pile up after installing a hundred apps you used once. But “clean slate” done by hand is a brutal weekend: reinstall everything, hunt down every credential, remember every config you set once and forgot. I knew that weekend was waiting, so I kept postponing a purchase I actually wanted.
Then the obvious thought landed: what if one curl-pipe-bash could port all my tooling and all my credentials onto a new machine, and I never had to think about it again?
The tooling was easy. The secrets were the problem.
I daily-drive the terminal, so “my setup” is mostly a list of brew packages and my dotfiles — a solved problem. The hard half was credentials. You can’t just git clone your SSH and GPG keys onto a fresh machine; that’s exactly the stuff you most need to protect.
But I had a head start. I already keep my passwords and OTPs in pass, the unix password manager, which encrypts everything with a GPG key. So the whole secret-restore problem collapses to one question: how do I get my GPG key onto a blank machine safely? pass leans on Pretty Good Privacy, so I’d encrypt the key bundle the same way (ba dum tss).
That left one ugly thing: everything I own, sitting behind a single passphrase I had to memorize, committed — encrypted — to a repo. That felt sketchy. A memorized password is the weak link in every system: reused, forgotten, or shoulder-surfed. I did not want my entire digital identity gated by a string living in my head.
Two things I couldn’t stop thinking about
Idempotency. I had zero illusions — this script was going to fail on the first run, and probably the fifth. I needed to run it over and over without it making a mess each time, which meant I needed a machine to test on. The Mac mini hadn’t arrived yet. So I looked at my home server and thought: why not make this run on Linux too? It’s all unix; the commands mostly carry over with a few caveats. Multi-OS support wasn’t some grand plan — it was me needing a test bed before the real hardware showed up.
Security better than a memorized password. And here the universe was weirdly generous: a swag drop from my employer landed, and their shop had YubiKeys in it. I grabbed one and fell straight down the physical-key rabbit hole.
The design that fell out: make the YubiKey the star of the show. The passphrase that decrypts the bundle isn’t in my head — it lives in the YubiKey’s static-password slot. The script asks for the passphrase; I touch the key instead of typing it. And because one physical key is one point of failure, the backup is my Flipper Zero — which had been lying around doing nothing for ages — holding the same secret. Two physical devices, zero memorized passwords.
How it actually runs
The whole thing is one command:
curl -fsSL https://raw.githubusercontent.com/victorstein/seed/main/bootstrap.sh | bash
Run it with --dry-run first and it prints exactly what it’ll do without touching a thing — the same idempotency instinct, just pointed at the user instead of the script. Then, in order, it:
- Installs the Xcode command-line tools and Homebrew.
- Imports my GPG key — this is the YubiKey moment. It prompts for the passphrase and I touch the key instead of typing.
- Restores my SSH keys from the encrypted bundle.
- Clones my dotfiles and links them into place.
- Installs every brew package.
The order isn’t arbitrary. GPG goes first because it’s the key that unlocks everything else — pass, SSH, the lot. SSH next, so the machine can actually talk to my repos. Then dotfiles and packages, the parts that are tedious rather than sensitive. Get the order wrong and step 4 can’t authenticate to clone anything.
And it runs on macOS and Linux — which, again, only exists because I needed somewhere to test it.
The irony, and where it stands
I finished encryption, idempotency, and multi-OS support in about two days. The migration I’d been dreading was supposedly a weekend; I spent roughly that long building the thing that made the weekend disappear — and walked away with a reusable skill and a reproducible machine instead of just a configured laptop. I’ll take that trade every time.
The bonus I didn’t fully see coming: it isn’t a one-shot tool. Every new node I add to my home server is fully set up — tooling and credentials — in minutes. So far seed has bootstrapped four machines: two nodes on my home server, the new Mac mini I finally let myself buy, and a remote box I pay for.
The secret that unlocks all of it lives in three places, none of them my memory: the YubiKey I touch, the Flipper Zero as backup, and — last resort — the same static string written down in an offline vault, nowhere near a computer. That one string is the only thing I genuinely can’t afford to lose. Everything else, I can rebuild in the time it takes to drink a coffee.