How I wired a $12 droplet into a personal cloud (Dokploy + n8n + Ghost + OpenCLAW)
I spent one evening this week ripping out half my managed services and replacing them with a single $12/mo DigitalOcean droplet. Here's what I built, what broke, and what I'd do differently.
The stack, top to bottom
- Dokploy — the PaaS layer. Open source, Traefik-powered, drops Let's Encrypt + Docker Swarm onto your box in one curl pipe. Think Heroku but you own the dial.
- n8n — workflow automation. The glue between Cal.com, ClickUp, Anthropic, Brevo, and anything with a webhook.
- Ghost CMS — what you're reading. Modern blog, members, newsletters.
- OpenCLAW — Coollabs' multi-channel AI agent gateway. Talks to Claude, Gemini, Z.AI, and forwards to Discord/Telegram/WhatsApp bots.
What it costs
The whole stack runs on a single droplet with these specs:
| Spec | Value |
|---|---|
| RAM | 2 GB |
| vCPU | 1 |
| Disk | 50 GB SSD |
| Region | Singapore (best ping from Dhaka) |
| Cost | $12/mo |
Add a 2 GB swapfile because n8n + Ghost + OpenCLAW will breach the 2 GB RAM ceiling within five minutes of you adding a second app. Swap is not free RAM, but it stops the OOM killer from murdering your services at 3 AM.
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl vm.swappiness=10The install dance
Dokploy bootstraps in about three minutes. SSH in, run:
curl -sSL https://dokploy.com/install.sh | shThat gives you a UI at http://your-droplet-ip:3000. Create the admin account, point a subdomain at the droplet IP, set the Dokploy server domain, and you've got HTTPS via Let's Encrypt on the dashboard itself.
From there it's templates. Ghost: one click + a domain. n8n: same. OpenCLAW: same, but smaller. Each gets its own subdomain, its own Let's Encrypt cert, its own backed-up volume.
The pothole — DigitalOcean blocks outbound SMTP
Try to send mail and you'll hit this:
Error sending email: Failed to send email. Reason: Connection timeout.
DigitalOcean blocks outbound ports 25, 465, and 587 by default on new droplets. Anti-spam policy. Doesn't matter that you're trying to send a single staff invite from your tiny blog — port 587 to smtp-relay.brevo.com just hangs.
My fix: write a tiny Python SMTP server (~120 lines using aiosmtpd) that accepts mail on port 587 inside the Docker network, parses each message, and POSTs it to Brevo's HTTPS REST API instead. Ghost connects to brevo-relay:587 by service name; the relay turns SMTP into api.brevo.com/v3/smtp/email calls. HTTPS isn't blocked, so mail flows.
Full write-up in the Brevo bridge post.
What I'd do differently
- Start with 4 GB. 2 GB on this stack means you're constantly courting swap thrash. $24/mo for 4 GB is fairer.
- Add the swap before the first deploy. Found this out the hard way when OpenCLAW's chromium sidecar requested 2 GB shared memory I didn't have.
- Pick CF proxy ON immediately for any public-facing service. n8n got bot-registered as owner within minutes of going live without it.
What you get for $12/mo
- Personal blog at
ghost.ahsanhabibakik.com(this one). - Workflow engine at
n8n.ahsanhabibakik.comrunning daily morning briefs and a Cal.com → ClickUp pipeline. - AI agent gateway at
openclaw.ahsanhabibakik.comthat can wire into Discord, Telegram, Slack, WhatsApp. - A PaaS dashboard to add more apps without touching docker-compose ever again.
About four hours of setup. Maybe less if you don't have to invent an SMTP-to-HTTPS bridge mid-flight.
Topics:
Want to Implement These Strategies?
I can help you apply these insights to your business. Book a free consultation today.
Book Your Free Consultation