← All posts

Docker Compose HomeLab Setup: From Zero to 8 Services Behind Cloudflare

May 29, 2026·#docker#infra#cloudflare

Bare-metal Linux → Docker Compose → NGINX reverse proxy → Cloudflare Tunnel. The exact setup running Maalig AI in production.

Docker Compose HomeLab Setup

This is the exact infrastructure setup running Maalig AI in production — no Kubernetes, no managed cloud, just Docker Compose on a bare-metal ASUS server.

The Hardware

ASUS server running Ubuntu 22.04. 32GB RAM, 8-core CPU, 2TB NVMe. More than enough for a SaaS with under 1,000 users.

The Stack

Cloudflare Tunnel
    └─ NGINX (reverse proxy)
        ├─ Angular SSR (web:4000)
        └─ NestJS API (api:3000)
            ├─ MongoDB (27017)
            └─ Redis (6379)

Docker Compose Structure

The key insight: separate networks for internal services. MongoDB and Redis are not exposed to the host — only the API container can reach them.

networks:
  maalig:
    driver: bridge

services:
  api:
    networks: [maalig]
  mongo:
    networks: [maalig]
    # No ports: exposed to host
  redis:
    networks: [maalig]
    command: redis-server --requirepass ${REDIS_PASSWORD}

Cloudflare Tunnel

No open ports on the server. Cloudflare Tunnel creates an outbound connection to Cloudflare's edge — traffic flows in through the tunnel, never directly to your IP.

cloudflared tunnel create maalig
cloudflared tunnel route dns maalig app.pmpksamy.com

Health Checks

Every service has a health check. Docker restarts unhealthy containers automatically.

healthcheck:
  test: wget -qO- http://localhost:3000/api/v1/health | grep -q '"status"'
  interval: 15s
  timeout: 5s
  retries: 3

Rolling Deploy

Zero-downtime deploys: pull new image → restart api → health gate → restart web → verify.

If health check fails at any step, the ERR trap fires the rollback function automatically.