DEV Community

Edgar Deven
Edgar Deven

Posted on

I Got Rejected by 3 Cloud Providers. My Laptop Didn't Care.

I needed to host a real client's CMS site. For free. That last part turned out to be the hard bit.

I'd built a modular, English-native Laravel CMS after switching off a Persian-language open-source project that needed more translation work than I had appetite for. Once the app was running cleanly in Docker locally, deployment seemed like the easy part. It was not.

Round 1: Oracle Cloud

Oracle's Always Free tier is genuinely the best deal in cloud hosting, 4 ARM cores, 24GB RAM, forever, for free. The catch: their identity verification is aggressive about rejecting virtual and prepaid cards, which is exactly the kind of card a lot of us outside the US/EU actually have access to.

Rejected.

Round 2: Hetzner

Cheap, reputable, well-documented. I tried creating an account to run alongside Laravel Forge.

Account rejected, no real explanation given, which I've since learned isn't unusual for accounts from certain regions without an existing payment history.

Round 3: Cloudways

This one actually worked. Managed PHP hosting, full SSH access, Laravel officially supported. I spent real hours getting it production-ready: chasing down a Redis ACL permission error that took four separate diagnostic passes to understand, discovering two leftover files from the original composer create-project scaffold that were silently colliding with TypiCMS's own migrations, and fixing an SSL certificate that had been issued for the wrong hostname.

I got it fully working. Then the free trial ended.

The realization

At some point, staring at a third rejected and expired hosting option, I asked myself the obvious question I'd been avoiding: my Docker setup already runs perfectly on my own machine. Why does it need to run somewhere else at all?

The two things standing between "runs on my laptop" and "reachable by anyone on the internet" turned out to be smaller problems than I'd assumed:
My laptop has no public address. It sits behind my home router like everyone's does.
Getting a real domain with HTTPS usually means server config I didn't want to hand-roll.

Cloudflare Tunnel solves both. It opens a secure, outbound-only connection from your machine to Cloudflare's edge, no inbound ports, no router configuration, works fine even behind CGNAT. Anyone visiting your domain talks to Cloudflare, which quietly forwards the conversation through the tunnel to your laptop. Free, automatic HTTPS comes along with it.

Twenty minutes later, my domain was live, served from the same laptop I was debugging it on.

The honest tradeoff

This isn't real production hosting, and I won't pretend otherwise. The site is only reachable while my laptop is on and connected. If I close the lid, the site goes down. That's a genuinely different reliability story than a VPS.

But for a client demo, a side project, or a real site while the client sorts out the an actual hosting budget, "free and mostly-always-up" beats "rejected everywhere I tried."

What I actually hit setting it up

A few things worth knowing if you try this yourself:

Mixed content / broken CSS. Cloudflare terminates HTTPS at their edge and forwards plain HTTP to your machine internally. Most frameworks don't know this and will generate broken http:// asset links unless you explicitly tell them to trust the proxy. In Laravel, that's one line: URL::forceScheme('https'); in your AppServiceProvide.
Containers don't survive a reboot by default. Docker itself restarting on boot doesn't mean your containers come back with it, every service in your docker-compose.yml needs restart: unless-stopped explicitly, or a reboot leaves your "working" setup silently dead.
cloudflared service install looks for its config in a specific place (/etc/cloudflared/config.yml), not wherever you happened to create your tunnel from, an easy, non-obvious thing to trip over the first time.
I packaged it up

Since I'd already worked through all of this the hard way, I turned it into a small, reusable, MIT-licensed toolkit: selfhost-tunnel-kit. It's an interactive script that automates the whole setup (install cloudflared, authenticate, create the tunnel, route DNS, install it as a persistent service), plus docs covering exactly the issues i have said above, written generically enough to apply whether you're running Laravel, Django, Express, or anything else in Docker.

If you've been putting off shipping something because every "free" cloud tier somehow isn't free for you either, try pointing a domain at your own machine instead. It works better than it has any right to.

Top comments (0)