At 2:53 PM on June 24, I had a freshly verified recovery bundle and the bad kind of confidence. It could restore the important parts of my machine. It could not restore the system that held the backup unless I already had cloud access.
That is not a backup plan. That is a dependency chain wearing a backup label.
If this developer machine disappeared, I wanted a bare clone of one bootstrap repository to rebuild the working setup. Repositories, local configuration, recovery material, and the path back to the operational backup had to return in an order that did not assume the machine, its credentials, or an authenticated cloud session survived.
The first implementation looked complete until I traced the chain backward. Our operational backup layer lived in R2. Reaching it required R2 credentials. Rebuilding the working repositories required SSH keys. Those credentials could not safely live inside the operational backup, because the restore process would begin by asking the backup for the keys needed to open the backup.
That is the bootstrap paradox. The thing that restores the system is part of the system that needs restoring.
Trace the failure from the blank machine
The useful diagnostic was not “do we have backups?” We do. It was: what can a blank machine do before it can authenticate to anything?
Starting there exposed three layers that I had blurred together:
bare machine -> clone the bootstrap repository -> read the self-maintaining repository manifest -> clone the working repositories -> decrypt the GPG cold-start bundle -> recover R2 credentials and SSH keys -> reach the operational backup layer -> restore the remaining local stateThe critical boundary sits between the fourth and fifth lines. The bootstrap repository can be cloned without the rest of the environment. The cold-start bundle can be decrypted without first reaching R2. Only then does the machine recover the credentials that unlock the larger backup layer.
I built the repository manifest to maintain itself because hand-maintained inventories fail quietly. A static list is accurate on the afternoon someone edits it. A repository added six weeks later becomes the missing piece you discover only during recovery. The manifest keeps the bootstrap repository’s clone map current, rather than relying on memory or a document nobody revisits under normal pressure.
That solved one class of failure. It did not solve the credential loop.
The secret that cannot be backed up with the backup
The cold-start bundle is encrypted with GPG and contains the R2 credentials and SSH keys that cannot live in the operational backup. I generated it and verified it as part of the build.
This is deliberately a smaller object than the backup it unlocks. It is not a duplicate of every secret and local file. It is the minimum recovery material required to get a blank machine through the authentication boundary.
I considered putting the credentials directly in the bootstrap repository, encrypted or otherwise. That lost immediately. A repository intended for bare cloning is the wrong place to normalize permanent access credentials. I also considered treating a shared drive copy as the recovery mechanism. That only moves the question sideways: what happens when the machine cannot reach the drive account, the login session is gone, or the credentials live in the state being restored?
Putting the bundle in R2 was worse. It preserved the encrypted files but left the restore sequence circular. The bundle had to live apart from the operational backup layer, protected by GPG and kept air-gapped from routine backup access.
The result is not no cloud. The operational backup still uses R2 because it is the right place for the full, living backup layer. The result is a recovery path that does not assume the backup is already available when it matters most.
Keep the cold-start layer boring
There is a temptation to make the bundle smarter. Add more automation. Put every environment variable in it. Turn it into a portable image of the machine. I rejected that direction because the bundle is not an operational convenience. It is a break-glass artifact.
Every additional secret increases what has to be rotated, verified, stored, and remembered. Every extra dependency makes the blank-machine path harder to reason about. The bundle needs to stay small enough that I can explain its role without exceptions: it supplies the credentials that open the backup and the keys that rebuild the repository layer.
The operational backup can change frequently. The cold-start layer should change only when the minimum path changes. Those are different cadences, and combining them would make both less trustworthy.
There is a human failure mode too. A GPG-encrypted bundle is only useful if the passphrase survives separately from the machine. A bundle that never leaves the machine is not a recovery artifact. It is another file on the failed device.
After verification, the remaining work was explicit: upload the bundle to a shared drive and save the passphrase through a separate channel. I also opened a blank-machine dry run. The generated bundle proved the design can exist. The dry run will prove whether the sequence works when there is no helpful shell history, no cached credentials, and no temptation to skip a step because I remember where something lives.
That is the test that matters. A backup is not a pile of copied files. It is an ordered recovery procedure with a first credential, a first repository, and a first command you can run when everything familiar is gone.
I built the first part on June 24. The next failure I care about is the one I can simulate before a real machine forces the issue.