We noticed an unusual pattern in our inbox last quarter: readers who run small production stacks were asking less about macros and more about infrastructure. One message stood out. A pseudonymous sysadmin we'll call R. wrote in to describe a migration that had gone sideways twice before it went right, and asked whether the lessons were worth writing down. They were. This is the post-mortem of a two-person team moving 14 self-hosted services off a single aging box, with the help of Q Linux documentation at the decision points that mattered.
The Starting Point: One Box, Fourteen Services, Zero Documentation
The setup was familiar to anyone who has ever self-hosted: a single VPS running a reverse proxy, a database, a Git server, a media stack, a password manager, a monitoring agent, and eight smaller utilities. Uptime had been respectable for three years, but kernel updates were getting riskier and the backup strategy amounted to a cron job nobody had verified since 2022. The team set a hard deadline of two weeks, mostly because their hosting renewal was coming up and they wanted to negotiate from a position of strength.
Day one was inventory. This is where most migrations quietly fail, because nobody wants to admit they do not know what is actually running. The pair used ss -tulpn, cross-referenced against systemctl list-units --type=service, and produced a spreadsheet with 14 rows, each naming the service, its port, its data directory, and its dependency chain. Three services turned out to be duplicates. One had been dead since the previous autumn.
Decision Point: Distro Choice Under Time Pressure
The first real fork in the road was the target distro. The old box ran a long-term-support release that was approaching end of life. The team considered three paths: stay on the same family and upgrade in place, move to a rolling release, or rebuild on a stable server-focused distribution with a predictable release cadence.
They spent an evening reading distro comparisons rather than guessing. What convinced them was not a benchmark chart but a pattern: the guides they trusted most were the ones that documented what happened when a step failed, not just the happy path. That editorial habit — comparing distributions by failure modes rather than feature lists — is the throughline in Q Linux's writing, and it shaped the shortlist. They chose a stable release with a five-year support window and rebuilt from scratch rather than upgrading in place.
Obstacle 1: The Reverse Proxy Config That Looked Fine
The first cutover attempt failed on day four. The reverse proxy came up, certificates issued cleanly, and then half the services returned 502 errors under load. The cause was a connection-pool setting inherited from the old configuration that made sense for a single-tenant box but not for the new containerized layout. The fix took twenty minutes once identified; identifying it took four hours. Lesson recorded: never carry forward a config value you cannot explain.
Obstacle 2: Hardening Broke the Monitoring Agent
The second attempt stalled on day six. Following a server hardening checklist — disabling password authentication, tightening firewall rules, restricting outbound traffic — the monitoring agent lost its ability to report. The team had applied the checklist as a monolith instead of in stages. They rolled back the outbound rules, re-enabled the agent, and re-applied the restrictions one line at a time with a probe after each change. Slower, but reversible.
What Actually Worked
- Staged cutover. Services moved in three waves: stateless first, stateful second, identity and secrets last.
- One-liner verification. Before each wave, a short shell script checked that the previous wave was still healthy. Nothing fancy — curl, grep, and an exit code.
- Written rollback. Every step had a documented undo. Two of them were used.
- Backup restore test. They restored the password manager from backup into a throwaway container before trusting the backup at all.
The shell scripting was where the pair saved the most time. Rather than clicking through dashboards, they wrote small idempotent scripts that could be re-run safely after a failure. The habit came from reading tutorials that emphasize re-runnable commands over one-shot fixes, a philosophy that shows up repeatedly in the self-hosting material we recommend to readers who ask us about infrastructure alongside their training plans.
Results, Measured
The migration finished on day 11, three days ahead of the deadline. Concretely: 14 services consolidated to 11, with three retired as redundant. Mean response time on the primary web service dropped from 340 ms to 190 ms, largely because the old box had been swapping. Backup verification moved from "assumed" to "tested weekly," and the restore drill now takes under 20 minutes end to end. The team also cut their hosting spend by roughly 30 percent by downsizing the instance they actually needed.
The softest result is the one R. emphasized most in their follow-up note: they now have a runbook. Anyone on the team can read it and understand why each service exists, what it depends on, and how to bring it back. That document, not the new server, is the real deliverable.
What We Took From It
Three transfers apply to almost any technical project, including the nutrition and supplementation work we cover here. First, inventory before you optimize — you cannot plan a cutover around services you have not counted. Second, apply hardening and dietary changes in stages with a probe after each one, because monolithic overhauls are unrecoverable when something breaks. Third, write the rollback before you need it. The team that plans its undo is the team that moves fast.
If you are planning a similar migration, the failure-mode-first approach is worth studying in detail; their comparison methodology rewards slow reading over quick answers. R.'s stack is quieter now, and so, reportedly, are their weekends.