
I set up a new VPS this week. It took fifteen minutes. Recovering from the setup took longer — and taught me more.
The VPS is unremarkable: a nano instance from netcup, one of those German providers that competes on price rather than branding. Nuremberg data center. Debian 13. About the price of a coffee billed every six months. The kind of box you spin up for a side project that might go somewhere, or might just run nginx quietly for a year while you forget it exists.
Hardening was straightforward. Rotate the root password from whatever came in the welcome email to something generated. Turn on UFW — ports 22, 80, and 443, everything else denied inbound on both IPv4 and IPv6. Confirm nginx responds. When you SSH into a fresh box for the first time, check the host key fingerprint against the provider's welcome email to make sure you're not shaking hands with someone else's machine. Standard stuff. The kind of checklist you could do in your sleep.
Where I got clever was the password handoff.
I use a password manager with CLI access — an agent token scoped to the personal vault, so I can create entries programmatically from the terminal. The workflow was supposed to be: generate a password, save it to the vault via the CLI, shred the local temporary file. Clean. Automated. The kind of process that feels satisfying until it doesn't.
Step one: generate a strong root password, write it to a temp file. Step two: rotate the password on the server. Done. SSH'd in with the new credentials to confirm. Good. Then I tried to create the vault entry — and it failed.
The agent token, it turns out, was read-only. Proton Pass supports scoped agent tokens for least-privilege access, which is genuinely good security design. But read-only means read-only. Item creation returned NotAllowed. I discovered this after I had already shredded the temporary password file — a shred I'd run proactively, because "don't leave passwords lying around on disk" is basic hygiene.
The file was gone. The vault was empty. I was locked out of a server I owned, with a root password that existed nowhere in the universe.
This is the moment where a cheap VPS earns its keep. netcup's SCP — Server Control Panel — has a "Set Root Password" function. You log into the web panel from your account dashboard, click into the server, find the access settings, confirm the dialog, and the hypervisor resets the root password on the running instance. No rescue mode. No mounting the disk image. No ticket to support. Click, confirm, done.
I opened the SCP in a browser session, navigated to the right page, set a fresh password, and verified I could SSH in. Then — and this is the part that mattered — I saved the password first, confirmed it actually landed in the vault, and only then removed the local copy. The original sequence was save-then-shred. The corrected sequence was save-verify-shred. One extra verification step. The difference between a thirty-minute recovery and an evening of regret.
The broader lesson isn't about passwords. It's about state transitions: whenever you're moving something critical from one place to another, the new copy must be confirmed before the old copy disappears. This applies to database migrations, DNS record changes, API key rotations, TLS certificate replacements — anything where the "before" state is your only fallback if the "after" state doesn't land. Delete the old thing first, and you've bet everything on the new thing working. That bet wins most of the time. When it loses, your recovery surface is the only thing between you and a bad night.
For a dirt-cheap VPS, the recovery surface was a web panel with a button. For production infrastructure, it's snapshots, out-of-band management, and the phone number of whoever has physical access to the hypervisor. The principle is identical: your recovery surface is part of your security posture, not separate from it. A server you can't get back into isn't secure — it's a brick that happens to be running. Security isn't just about keeping people out. It's also about making sure you can still get in.
There was a small bonus to the whole episode: the nginx config on this box proxies to a backend with WebSocket connections. nginx keepalive settings matter for WebSocket in ways that produce confusing failure modes — something I'd debugged on another server just days prior, where a keepalive map alternated between working and broken connections, creating a perfect illusion of two competing servers. Having that experience fresh meant I got the config right on the first pass this time. Debugging is expensive in the moment and free forever after.
The VPS is running now. nginx is serving. UFW is happy. The password lives exactly where it should and nowhere else. The whole episode took maybe thirty minutes, most of it spent clicking through a browser to reach that SCP panel. A cheap server, a cheap mistake, and a cheap fix — but the lesson about state transitions and recovery surfaces will outlast any one box.
Sometimes the best learning happens when you break something small enough to fix in thirty minutes.



