For years my personal projects lived on the same shared server as client sites. It was convenient. And it was wrong.
In early September I separated them: a small server at Hetzner — emre-vps — with a WireGuard tunnel on it.
Why separate
The technical reasons are secondary. The real one is responsibility:
- Entangled resources. Something I am experimenting with eating CPU means client sites slow down.
- Entangled risk. A port opened for a personal experiment is a port opened on the machine holding client data.
- Incident separation. If there is ever a security event, you cannot answer “did this come from my experiment or from a client site?”
The third decided it. I lived through one real incident on that shared server, and separating everything by hand took days.
This server hosts no client work. Corporate work and client accounts stay on the old server. The boundary is one sentence with no exceptions — the moment there is an exception, the separation is over.
Choosing the hardware, with numbers
The cheapest tier I wanted was entirely sold out. The next one up was four times the price for the same cores. I took the one in between.
Location was chosen by measurement:
| location | latency from my PC | decision |
|---|---|---|
| Falkenstein | 46 ms | chosen |
| Helsinki | 79 ms | — |
Being in the same data centre as the old server also minimised latency between them — useful if I ever need to move something.
The same logic decided the web server: the sites on the old machine use .htaccess. Installing the same web server reduces a migration to copy-and-paste. At this traffic level the performance difference is not measurable; the ease of migration is.
The tunnel
I chose WireGuard for simple reasons: fifteen lines of configuration, near-instant connection setup, and no battery drain on mobile.
There are three clients and all three are different:
emre-vps-pc-full.conf PC — all traffic through the tunnel
emre-vps-pc-split.conf PC — only internal networks routed
emre-vps-phone-full.conf phone — full tunnel
emre-vps-quest-full.conf VR headset — full tunnel
The PC has both because both are needed:
- Full tunnel — on a hotel or café network. Everything through the tunnel, nothing in the open.
- Split tunnel — at home. Only server-bound traffic is routed; video and downloads go direct. Latency and bandwidth are preserved.
And the VR headset
This was the most entertaining part. A VR headset has no VPN app in its store. But the device is Android-based, so in developer mode the app can be sideloaded.
I wrote a setup script for it: connect the device, install the client, push the configuration.
Then I measured the tunnel — “connected” is not enough:
ping from headset to server → 10.10.10.4 replied
traffic transferred → ~11 MB
verified end to end ✓
The indicator can be green while no traffic passes at all — wrong routing, a DNS leak, or a key mismatch. The only real test is getting a reply from the other side and seeing the byte counters move.
This is the same class of error as a watchman counting the wrong stage: a status indicator and reality are different things.
The real obstacles during setup
I took a second server too (for testing) and hit an unexpected wall there.
The provider forces a password change on first login for password-provisioned servers. No automation can get past it: none of the tools can present a real terminal, and the process dies with “no TTY available”.
The first login has to be interactive. After changing the password by hand once, everything after it automated fine.
A good illustration of automation’s boundary: some steps are deliberately made un-automatable.
An AI session on the server
I set up a Claude Code session on the test server, inside a persistent terminal session so it survives a dropped connection.
And an interesting trap appeared: a stale credential token sat in the shell start-up file and every new session inherited it. The result: the account session was overridden and remote access broke.
The fix was to unset that variable explicitly. The same pattern appeared in the voice assistant: a child process must not be affected by who launched it.
What I learned
The cost of a separate server is a few coffees a month. What it bought me is not capacity — it is a mental boundary.
I no longer pause before trying something to ask “could this affect a client site?”. Once that hesitation went, the number of things I try went up.