Docker management, monitoring that goes deeper than a green dot, backups I have actually restored, and everything else that showed up once deploying stopped being the hard part.
Moving off Vercel solved exactly one problem: deploying. Everything else I used to get for free, quietly, as part of the platform, I now had to go find and wire up myself. A month into running my own server, I had a list of ten tools taped to the inside of my head, each one solving a problem I did not know I had until it happened to me at a bad time.
This is that list, in the order I actually needed them, with the mistake or the moment that made me install each one. I lean JS and Rust wherever I can, partly out of preference and partly because those are the tools that keep pace with how fast the rest of my stack moves. A couple of these are not JS or Rust at all, and I kept them anyway because they were simply the best tool for the job.
1. Dokploy, for everything I wrote about yesterday
This is the one I already spent an entire post on, so I will keep it short here. Push to main, Dokploy builds the container, Traefik points a domain at it, done. Four apps running on one $24 droplet, and adding a fifth would not move the bill. If you deploy anything with Docker and are still doing it over SSH, start here. Everything else on this list assumes you already have a platform under you, not just a server.
2. Neon, for the database half of preview environments
The first crack after Dokploy was previews. Dokploy gives every pull request its own preview URL, which is one of the nicest things about the whole setup, right up until every preview hits the same production database. I corrupted a batch of test data twice before I noticed what was happening. Neon branches Postgres the way git branches code, copy-on-write, so a preview PR gets its own preview database that costs almost nothing until it actually diverges from main. The storage engine underneath is written in Rust, and it quietly closed the other half of preview environments that nobody's setup guide mentions.
3. OpenObserve, for monitoring that actually explains itself
Dokploy's own dashboard will tell you a container is using too much memory. It will not tell you why, which request caused it, or whether it has happened before. I moved to OpenObserve for that: logs, metrics, and traces in one place, shipped as a single Rust binary, one docker-compose file to run it. The first afternoon I had it wired up, I found a query that had been running slow for three weeks, in the trace waterfall, in about four minutes. My old approach to that same investigation was grep and vibes.
4. restic, for the backups Dokploy does not know about
Dokploy's built-in backups cover Postgres, and I use them. They do not cover the config folder for my API, a SQLite file one of my smaller tools writes to, or a volume attached to a service that is not a database at all. restic backs up anything, encrypts it before it leaves the box, deduplicates so a nightly backup of a mostly-unchanged folder costs almost nothing in storage, and restores with one command I have run on purpose more than once, just to check.
restic -r s3:https://<account>.r2.cloudflarestorage.com/backups backup /var/lib/myapp
restic -r s3:https://<account>.r2.cloudflarestorage.com/backups restore latest --target /tmp/restore-test
It ships as a single static binary, which after living through more dependency hell than I would like to admit, I have come to treat as a feature in its own right.
5. Sentry, for the bugs logs make you scroll past
Logs tell you something broke. They do not tell you it broke for the same handful of users, three times a day, on the same line of code, until you have already lost interest in scrolling through them. Sentry groups the exception, attaches the stack trace, and tells me exactly which release introduced it. The self-hosted stack is heavier than I would like, but the JS SDK alone, dropped into a Next.js app, has caught more real bugs before a user reported them than anything else on this list.
6. OpenReplay, for the tickets that just say “it's broken”
A user once emailed to say a form “just doesn't work,” with no other detail, which used to mean opening dev tools and hoping I could reproduce it. OpenReplay records the session and replays it back like a video, console errors and network requests included, exactly as the user hit them. It is open source and self-hosted, and it has turned half-day investigations into two-minute videos more times than I can count.
7. Appium, for testing on an actual device instead of a hunch
Once a project had a real mobile wrapper around it, testing it by hand on my one physical phone stopped being a strategy. Appium drives real devices and simulators the same way Selenium drives a browser, through the WebDriver protocol, so the same testing habits carry over. I script the login flow and the checkout flow on both iOS and Android before every release, and it has caught two platform-specific bugs that a browser would never have shown me.
8. k6, for finding the ceiling before traffic does
A newsletter mention once doubled my traffic for six hours. The API held, barely, and I had no idea by how much margin. k6 lets me write load tests in JavaScript, the same language as the thing being tested, and run them against staging before a launch instead of finding the ceiling live.
import http from 'k6/http';
export const options = { vus: 500, duration: '2m' };
export default function () {
http.get('https://staging.myapp.com/api/health');
}
Ten minutes to write that tells you more than any amount of guessing.
9. Infisical, for replacing a very bad system
My “secrets management” before this was environment variables pasted into Dokploy's UI and, if I am honest, a couple of .env files sitting in a private Slack channel. Infisical is open source, written in TypeScript, and gives every project versioned secrets, per-environment values, and an audit log of who changed what. Rotating a leaked key used to mean a search-and-replace across three servers. Now it is one dashboard and a redeploy.
10. n8n, for the glue that runs everything else
n8n is the part that quietly holds the other nine together. When OpenObserve crosses an alert threshold, when a restic backup fails, when a new signup needs a welcome sequence, n8n is the thing that notices and does something about it, wired together as a workflow instead of a script I will forget I wrote. It runs on Node, it is free to self-host, and it is the tool I have extended the most since installing it, because every new problem seems to end with “I should probably wire that into n8n.”
So, is this too many tools for a side project?
Maybe. Ten tools running on one box is still one box, and the more of these you add, the more you are choosing to own instead of rent. What changed for me is that each one solves a problem I actually had, in the order I actually had it, rather than a checklist I installed on day one and mostly ignored. If you are one platform migration into doing this yourself, start with whichever one of these already hurts.