◆ Case Study · Self-Hosted Stack

Replace $400/mo of SaaS with One Oracle Cloud VM

A production-grade self-hosted ops stack designed for founders and lean teams. n8n, PostgreSQL, Redis, Listmonk, Mautic, Chatwoot, Umami, Traefik with auto-SSL, all on a single Oracle Cloud free-tier ARM VM. 21 containers, ~2.7 GB of 24 GB used, no SaaS lock-in, under two hours from empty machine to provisioned stack.

21
Containers / 1 VM
2.7
GB RAM used / 24
Free-tier
Eligible hosting
~$400
/mo SaaS replaced
< 2h
Bare metal → live
Reference deployment
Running in production across multiple engagements
What It Replaces
SaaSTypical costSelf-hosted equivalent
Zapier / Make$20–80/mon8n + Worker
Mailchimp / SendGrid$30–100/moListmonk
HubSpot / ActiveCampaign$50–150/moMautic
Intercom / Drift$75–200/moChatwoot
Google Analytics + Plausible$0–20/moUmami
Heroku / Railway$25–100/moOracle Cloud free ARM VM
Cloudflare Pro$20/moTraefik + Let's Encrypt
Total floor~$220–670/mominimal
The calculation doesn't count add-ons and overage charges — the moment a list crosses 5K contacts or a Zap hits its task limit, SaaS pricing jumps a tier. The self-hosted version is flat.
Tech Stack

Base

Oracle Cloudfree-tier ARM (Ampere A1)
Ubuntu 22.04 LTSARM64
Docker + Compose v2all services
Traefik v3auto-SSL, routing

Data

PostgreSQL 16multi-tenant schemas
Redis 7queue + cache
Backupsdaily pg_dump → offsite
Volumesmounted + snapshotted

Apps

n8n + n8n-workerqueue mode
Listmonknewsletter
Mauticmarketing automation
Chatwootomnichannel inbox
Umamianalytics
Single-VM Architecture

The entire stack runs on one Oracle Cloud ARM instance (4 cores, 24 GB RAM). Traefik terminates TLS on ports 80/443 and routes subdomains to the right container over an internal Docker network. PostgreSQL and Redis are shared between services but accessed over the private network only. Every container has a health check and a restart policy — if something crashes at 3 AM, the stack self-heals before anyone notices.

Edge · Traefik v3
80/443 · automatic Let's Encrypt · subdomain routing · HTTP→HTTPS · basic-auth middleware · rate limits
n8n + worker
n8n.{client-domain}
Listmonk
mail.{client-domain}
Mautic
marketing.{client-domain}
Chatwoot
chat.{client-domain}
Umami
analytics.{client-domain}
CDN
cdn.{client-domain}
Shared data layer
PostgreSQL 16 (multi-schema) · Redis 7 (queue + cache) · docker volumes · daily pg_dump → offsite
Host · Oracle Cloud free-tier ARM
4 vCPU (Ampere A1) · 24 GB RAM · 200 GB block volume · free-tier eligible · Ubuntu 22.04 LTS
Resource Budget
ComponentContainersApprox RAM
Traefik1~80 MB
PostgreSQL 161~400 MB
Redis 71~60 MB
n8n + worker2~500 MB
Listmonk1~150 MB
Mautic (app + php-fpm + nginx)3~450 MB
Chatwoot (web + worker + sidekiq)3~600 MB
Umami1~100 MB
Supporting (CDN, backups, metrics)8~350 MB
Total21~2.7 GB / 24 GB
Ops & Hardening
ConcernHow it's handled
SSL / certsTraefik + Let's Encrypt, auto-renew, wildcard where needed
BackupsDaily pg_dump cron, encrypted, shipped offsite (S3-compatible)
Secrets.env files per service, never committed, rotated via one script
MonitoringContainer healthchecks + Uptime Kuma, Telegram alerts on failure
FirewallOracle security list + ufw, only 22/80/443 exposed
UpdatesWeekly apt upgrade + staged container image bumps with rollback
Everything is reproducible from a single docker compose up -d against a committed compose file and environment. Rebuild on a new VM is under two hours — from empty Oracle instance to fully routed stack with SSL.
Engineering Challenges Solved

🛠️ ARM64 Everywhere

Oracle free tier is ARM. Many official Docker images still ship x86-only or lag behind on multi-arch.

Solution: Every service in the stack is either an official multi-arch image or a pinned community ARM64 build. Chatwoot and Mautic required extra care — in each case I documented the specific tag that works and the upgrade path.

🔒 SSL Without Cloudflare

Most guides assume Cloudflare or a paid cert provider. That adds an external dependency and another bill.

Solution: Traefik v3 native Let's Encrypt integration with HTTP-01 challenge. Every subdomain gets a cert on first hit, renewals are automatic, and there is no external service in the critical path.

📊 Shared Postgres Without Chaos

Running one Postgres for n8n, Mautic, Listmonk and Chatwoot sounds dangerous — one bad migration can take everything down.

Solution: Strict per-service schemas and users with least-privilege grants. pg_hba.conf restricts internal networking only. Backups are per-schema so a restore of one service never touches the others.

🔄 Safe Upgrades

Pulling latest on a production Mautic or Chatwoot image is a good way to destroy a week.

Solution: Every image tag is pinned in compose. Upgrades go through a staging volume + dry-run migration first. Rollback is one line: change the tag back and restart the container.

💻 RAM Pressure

Chatwoot's Rails + Sidekiq stack is hungry. Naive defaults push past 1 GB for a single service.

Solution: Tuned Unicorn/Sidekiq worker counts per container, Ruby GC tweaks, and realistic cache sizes. Final footprint is ~600 MB for all three Chatwoot containers combined and the whole VM sits at ~2.7 GB of 24 GB.

📥 Deliverability Without a $100 ESP

Self-hosted email has a reputation problem: either it lands in spam or you pay a commercial ESP anyway.

Solution: Listmonk pointed at a cheap SMTP relay (Brevo free tier, 300/day, or AWS SES) instead of hosting outbound MTA. You get the warm IP reputation of a real ESP and the full control of self-hosted tooling — the best of both.
💡 This is the exact stack I bring into consulting engagements where a client wants to consolidate their SaaS spend without giving up features or handing the keys to a DevOps team that doesn't exist yet.
Results & Metrics
21
Containers
on 1 VM
2.7GB
RAM used
of 24 GB
Free-tier
Hosting eligible
or low-cost VPS
~$400
/mo SaaS
replaced
Headroom & Savings

Capacity Headroom

RAM used~2.7 GB / 24 GB
CPU load~0.3 avg / 4 cores
Disk~25 GB / 200 GB
Room to add5–10 more services

Monthly SaaS Avoided

AutomationZapier / Make
EmailMailchimp / SendGrid
CRM / MarketingHubSpot / ActiveCampaign
ChatIntercom / Drift
AnalyticsGA / Plausible
HostingHeroku / Railway

Reliability

SSL renewalautomatic
Backupsdaily offsite
Uptime monitorUptime Kuma
AlertsTelegram bot
Deliverables
  • 💾
    docker-compose StackSingle committed compose file provisioning all 21 containers, with environment templates and volume definitions
  • 🔒
    Traefik + Let's Encrypt ConfigAutomatic SSL, subdomain routing, rate-limiting and basic-auth middlewares — zero cert maintenance
  • 📊
    Shared Postgres + RedisSchema-per-service isolation, least-privilege users, backup rotation, restore-tested
  • 📩
    Email PipelineListmonk + SMTP relay integration for high deliverability without an in-house MTA
  • 📝
    Runbook & Upgrade PlaybookStep-by-step docs for backups, restores, image upgrades, rollback, and common incidents
  • 🔌
    Monitoring + AlertsUptime Kuma dashboard + Telegram bot notifications on any container failure or cert issue
Technology Tags
Oracle Cloud ARM64 Ubuntu 22.04 Docker docker-compose Traefik v3 Let's Encrypt PostgreSQL 16 Redis 7 n8n Listmonk Mautic Chatwoot Umami Uptime Kuma Self-Hosted DevOps Infra Consolidation

Want to Kill Your SaaS Bill?

I migrate founders and lean teams off SaaS stacks into self-hosted infrastructure they actually own. Fixed scope, fixed price, runbook + handover included. Same stack I run for production environments, deployed for yours.

💬 Hire Me on Contra ← Back to portfolio
What I Build

Voice AI Agents

Inbound receptionistsAny language
Outbound sales agentsCold + warm
Appointment bookingReal-time CRM
Emergency routingLive transfer

Content Automation

AI content generationMultilingual
Blog & social publishingMulti-platform
Email drip campaignsFull funnel
Trend intelligenceAutomated

Video Production

AI script writingNative multilingual
AI image generationGPT Image
TTS voiceoverWaveNet voices
Remotion renderCustom templates

Infrastructure

N8N workflowsSelf-hosted
PostgreSQL + RedisProduction-grade
Monitoring & alerts24/7
DocumentationRunbooks + guides
Based in Honduras (UTC-6). Available for async collaboration across all timezones. Fluent in English, Spanish, and French.