My Self-Hosted DevOps Stack

April 10, 2026

This is the actual stack I run across all my client projects and personal deployments. No Vercel. No Railway. No Heroku. Full ownership of every layer.

Compute — OCI and AWS

I run the majority of workloads on Oracle Cloud Infrastructure (OCI) ARM instances. The free tier is genuinely useful for production — 4 OCPUs, 24 GB RAM, and 200 GB block storage at no cost. For heavier or latency-sensitive workloads, I use AWS EC2 with CloudFront for CDN.

The split:

  • OCI — most React apps, static sites, smaller SaaS workloads, personal projects
  • AWS EC2 + CloudFront + S3 — higher-traffic client projects, media delivery, email via SES

Both get Cloudflare in front for DNS, CDN, WAF, DDoS protection, and caching rules.

Server Management — CloudPanel

CloudPanel is my server management layer. It handles:

  • Node.js apps — PM2 process management, reverse proxy, automatic restarts
  • WordPress — PHP-FPM, Nginx, MySQL, one-click SSL
  • Static sites — served directly with Nginx
  • Python and PHP apps — via reverse proxy
  • SSL — Let's Encrypt auto-renewal built in

Why CloudPanel over cPanel, Plesk, or raw Nginx config? It supports the full range of site types I need — Node.js, WordPress, PHP, static, and custom reverse proxies — in a clean interface without the bloat or licensing cost.

The alternative was managing Nginx configs and systemd services by hand. CloudPanel gives me that control when I need it, with sensible defaults when I don't.

Database — Self-Hosted PostgreSQL

All relational data goes to a self-hosted PostgreSQL instance, running on OCI. I manage it directly — no RDS, no managed hosting.

Why self-hosted?

  • Full access to extensions: pgvector for RAG and semantic search, pg_cron for scheduled jobs, PostGIS if needed
  • No per-row or per-connection pricing
  • I control backups, replication settings, and retention

Backups go to OCI Object Storage on a cron schedule. I run pg_dump + compression + encrypted upload. Restore is a single script.

Document Store — Self-Hosted MongoDB

For schema-flexible data — content queues, AI pipeline outputs, session data, crawl results — I run MongoDB on OCI.

Again, self-hosted by choice. I use Mongo for workloads where the document model genuinely fits. PostgreSQL handles structured relational data; Mongo handles the rest.

Background Jobs — Redis + BullMQ

Task queues run on BullMQ backed by a self-hosted Redis instance.

Use cases:

  • AI content generation pipelines — queued and rate-limited per model
  • Email delivery queues via SendGrid/SES
  • Scheduled crawl jobs for SEO monitoring
  • Retry logic for webhook deliveries

BullMQ gives me named queues, retries, delays, concurrency controls, and a dashboard. Redis handles the actual queue state. The combination is robust enough that I've never needed a managed queue service.

CI/CD — GitHub Actions Self-Hosted Runners

Every project deploys automatically on push to main via self-hosted GitHub Actions runners installed on the same OCI/AWS servers.

The workflow:

  1. Push to main
  2. Runner pulls the latest code
  3. Installs dependencies, runs the build
  4. Deploys via rsync to the site directory
  5. Reloads PM2 (for Node.js) or reloads the PHP-FPM pool (for WordPress)

Cost: zero. No GitHub Actions minutes consumed. No third-party CI bill.

I covered the full setup in Self-Hosted GitHub Actions for Zero-Cost Automated Deployment.

Security Layer

Every deployment goes through the same checklist:

  • Cloudflare WAF — blocks common attack patterns and bad bots before they hit the origin
  • SSL/TLS — Let's Encrypt certs via CloudPanel, Cloudflare full-strict mode
  • OWASP Top 10 — reviewed on every project before launch
  • Fail2Ban — SSH brute-force protection on every server
  • Role-based access — no shared root passwords, deployment user has minimum required permissions
  • Uptime monitoringArgonWatchGO, my open-source Go tool, monitors all services and alerts on downtime

Summary

LayerTool
ComputeOCI ARM + AWS EC2
CDN / WAFCloudflare
Server managementCloudPanel
Relational DBPostgreSQL (self-hosted)
Document DBMongoDB (self-hosted)
Cache / QueuesRedis + BullMQ
CI/CDGitHub Actions self-hosted
Uptime monitoringArgonWatchGO

The whole stack costs me very little per month for most projects. I trade managed-service convenience for full control, lower costs, and no vendor lock-in. For client projects, the savings go directly to the client. For personal projects, it means I can run more things without worrying about bills.

GitHub
LinkedIn
X