Replacing Vercel with an Old Laptop

At some point I realized my projects were spread across three different hosts without me ever really deciding on that. Pulse was on Railway, a few sites were on Vercel, and some odds and ends were on Cloudflare. None of it was expensive on its own, but there was no single place to look when something broke, and each service had its own idea of what a deploy was supposed to be. So I decided to pull all of it onto one machine I owned.

The machine

The machine I settled on was an old laptop I already had sitting around, which I gave more RAM and an SSD, and that was the entire hardware project. It's quiet, it's paid for, and for the kind of traffic my projects get it's more computer than I actually need.

Coolify first, then Dokploy

I started with Coolify, which is the obvious first answer when you go looking for a self-hosted platform. It does work, I just found it clunky to actually use, with enough small friction in the UI that I kept dreading going into it. That's a bad sign for something I expected to look at every time I deployed anything.

So I went looking again and landed on Dokploy, which is younger and leaner and mostly stays out of my way. That was most of the decision, honestly. It isn't perfect, and I've got a short list of things I wish it did that I'll get to at the end, but it's the one I stuck with.

How the routing works

This is the part I actually spent time on. I'm going to stay vague about the specifics, since publishing the exact shape of my own setup isn't a great idea security wise, but the general design is worth describing because it's what makes the whole thing pleasant to use.

Nothing on the server listens on a public port. Instead, a Cloudflare Tunnel makes an outbound connection to Cloudflare, and everything comes back down through that. In Dokploy this is just another application: Docker provider, the cloudflare/cloudflared image, the tunnel token as an environment variable.

What makes it easy is that the routes are all wildcards. Every domain I own gets a * CNAME aimed at the tunnel and a matching wildcard route in the tunnel config, and every one of those routes points at the same place, which is Dokploy's Traefik container. So any subdomain of any of my domains, at any path, lands in the same spot. Traefik then reads the hostname and hands the request to whichever service has claimed it.

Dokploy Server Browser Cloudflare cloudflared tunnel software Traefik routes by hostname Pulse Statbotics Everything else tunnel
Wildcard routes point every domain at the same tunnel, and Traefik sorts out where each request goes.

Security is the scary part

This was the scariest part of moving off managed hosting for me. On Vercel or Railway, someone else is paid to worry about who can reach the box. Once it's my machine, that's my problem, and my machine is sitting in my house.

Going through a tunnel handles most of it on its own. The connection is outbound only, so there's no open port on my router for anyone to find, and my home IP never shows up in DNS. Anything trying to reach my apps has to come through Cloudflare first, which means it gets Cloudflare's DDoS protection and firewall rules on the way in whether it likes it or not.

Then the endpoints that should only ever be reachable by me sit behind Cloudflare Access. Cloudflare puts a sign-in page in front of them before a request ever touches the server. Access denies everything by default and I write policies for who gets in, so the private stuff is guarded at the edge rather than by whatever auth I felt like building into the app that day. The Dokploy dashboard itself is one of those.

I also leaned on the rest of Cloudflare's security settings more than I would have on a managed host, since it's free and it's the layer everything already passes through anyway. None of that makes the setup bulletproof, but it does mean the surface I have to think about is small and all in one place.

Actually deploying something

The payoff for all that setup is that adding a project is now close to nothing. I point a subdomain at the tunnel, or skip that entirely if the wildcard already covers it, then set the domain on the service in Dokploy and pick the port, and that's the whole process. It's the same two minutes of work Vercel or Railway asks for.

Build times land in the same place too. Dokploy builds with Nixpacks or a Dockerfile, and on this server a typical app builds about as fast as it did on Railway. I expected to give something up there and didn't.

This is what's running Pulse now, along with my own modified Statbotics instance, which was the loose end I complained about in the Pulse post and finally got around to. Plus a pile of smaller tools.

Where it did cost me was the initial setup, since getting the tunnel, Traefik, and Access to all agree took longer than I'd like to admit. The tunnel can point straight at a single container and skip Traefik, which works, and it's the setup I'd have ended up with if I'd stopped as soon as the first app loaded. The problem with it doesn't show up until later, when every new app needs its own route added in Cloudflare. Handing everything to Traefik instead is the difference between configuring Cloudflare once and configuring it forever.

What I want from Dokploy

There are two things I keep wishing it did, and the bigger one is monitoring. I can look at the server, and I can look at a single service, and both of those are fine as far as they go. What I want is a task manager: one screen listing every container on the server with live CPU and memory, sorted by whatever is eating the machine right now. When something's slow I want to find the culprit in one glance instead of clicking through services one at a time. Other people have asked for this too, so maybe it's coming.

The smaller one is that remote servers are a one-way decision: I pick a server when I create a service and that's where it lives. There's no moving it later, so outgrowing a box or just wanting to shuffle things around means recreating the service on the new server and copying the volumes over by hand. That one's been requested a few times too.

Neither of those has cost me anything real yet. They're the two places where I notice I'm not on a managed platform.

Would I go back

I don't think I would, and the main reason is that this setup just feels elegant in a way the old one never did. Everything lives on one machine, adding to it costs me a domain and a port, and I can see all of it at once instead of logging into three dashboards to work out where something went. On top of that I have far more control than I used to. Dokploy is open source, so if something about it bothers me enough I can go change it myself, which was never going to be an option on Vercel or Railway.

It's also turned out sturdier than I expected going in. I've had it running for a while now and it's been noticeably more stable than Railway was, which I did not see coming, since I assumed the machine in my house would be the flaky one in this story. Dokploy also backs up the whole server config along with the volumes, so if the machine ever dies I'm restoring from a snapshot instead of rebuilding the whole thing from memory.