Docker, Nginx & Linux Stack Visual Composer
Visually compose production container stacks: select Nginx/Cloudflare ingress, frontend, backend API, databases & Redis. Generates SVG topology, docker-compose.yml, and UFW scripts.
Input Parameters
Calculation Results
- Stack Project Name
- kampus-app
- Production Target Domain
- app.example.com
- Total Active Containers
- 7 Containers
- Estimated RAM Memory Usage
- 1872 MB
- Recommended VPS Specification
- 4 vCPU / 4 GB RAM
- Security Posture & Isolation
- ZERO-TRUST TUNNEL (0 Port Web Terbuka di IP Publik + DB Terisolasi)
Validate firewall rulesets and cron timers in staging before production rollout.
| Container Service Name | Service Role | Docker Image Base | Container Internal Port | Public WAN Exposure | Estimated RAM |
|---|---|---|---|---|---|
| nginx-proxy | Edge Reverse Proxy & SSL Termination | nginx:1.27-alpine | 80, 443 | 127.0.0.1:8080 (Local/Tunnel) | 96 MB |
| cloudflared | Zero-Trust Outbound Tunnel (Zero Open Inbound Port) | cloudflare/cloudflared:latest | Outbound QUIC/HTTP2 | TERTUTUP (0 Port Terbuka di IP Publik VPS) | 80 MB |
| frontend | Next.js SSR Frontend | node:20-alpine | 3000/tcp | Internal Only (stack-net) | 384 MB |
| backend-api | Laravel PHP 8.3 (Octane/FrankenPHP) | dunglas/frankenphp:1-php8.3-alpine | 8000/tcp | Internal Only (stack-net) | 512 MB |
| database | PostgreSQL 16 Relational DB | postgres:16-alpine | 5432/tcp | Terisolasi penuh di db-net (Tanpa Port Publik) | 512 MB |
| redis-cache | Redis 7 In-Memory Cache & Session Store | redis:7.4-alpine | 6379/tcp | Terisolasi penuh di db-net | 128 MB |
| uptime-kuma | Uptime Kuma Status & Health Monitor | louislam/uptime-kuma:1 | 3001/tcp | 127.0.0.1:3001 (Internal/Tunnel) | 160 MB |
# =====================================================================
# Generated by InfraCalc Visual Stack Composer (https://infracalc.web.id)
# Project : kampus-app (app.example.com)
# Topology: BOTH_NGINX_AND_CF -> frontend + backend-api -> POSTGRES_16 + redis
# =====================================================================
name: kampus-app
services:
nginx-proxy:
image: nginx:1.27-alpine
container_name: kampus-app-nginx
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
depends_on:
- frontend
- backend-api
networks:
- edge-net
cloudflared:
image: cloudflare/cloudflared:latest
container_name: kampus-app-tunnel
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN}
networks:
- edge-net
frontend:
image: node:20-alpine
container_name: kampus-app-frontend
restart: unless-stopped
working_dir: /app
environment:
NODE_ENV: production
NEXT_PUBLIC_API_URL: https://app.example.com/api
expose:
- "3000"
networks:
- edge-net
backend-api:
image: dunglas/frankenphp:1-php8.3-alpine
container_name: kampus-app-backend
restart: unless-stopped
working_dir: /app
command: php artisan octane:frankenphp --host=0.0.0.0 --port=8000
environment:
APP_ENV: production
PORT: 8000
DB_HOST: database
DB_PORT: 5432
DB_NAME: ${DB_NAME:-app_db}
DB_USER: ${DB_USER:-app_user}
DB_PASSWORD: ${DB_PASSWORD}
REDIS_URL: redis://redis-cache:6379
expose:
- "8000"
depends_on:
database:
condition: service_healthy
networks:
- edge-net
- db-net
database:
image: postgres:16-alpine
container_name: kampus-app-db
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME:-app_db}
POSTGRES_USER: ${DB_USER:-app_user}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-app_user} -d ${DB_NAME:-app_db}"]
interval: 10s
timeout: 5s
retries: 5
networks:
- db-net
redis-cache:
image: redis:7.4-alpine
container_name: kampus-app-redis
restart: unless-stopped
command: redis-server --save 60 1 --loglevel warning --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
networks:
- db-net
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: kampus-app-monitoring
restart: unless-stopped
ports:
- "127.0.0.1:3001:3001"
volumes:
- kuma-data:/app/data
networks:
- edge-net
networks:
edge-net:
driver: bridge
db-net:
driver: bridge
internal: true
volumes:
db-data:
redis-data:
kuma-data:# =====================================================================
# Nginx Reverse Proxy Configuration ā Generated via https://infracalc.web.id
# Domain: app.example.com
# =====================================================================
upstream frontend_upstream {
server frontend:3000;
keepalive 32;
}
upstream backend_upstream {
server backend-api:8000;
keepalive 32;
}
server {
listen 80;
server_name app.example.com;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
client_max_body_size 25M;
# Backend API Route (/api/* -> backend-api:8000)
location /api/ {
proxy_pass http://backend_upstream;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Root Route (-> frontend:3000)
location / {
proxy_pass http://frontend_upstream;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}#!/usr/bin/env bash # ===================================================================== # Ubuntu/Debian VPS & Docker Firewall Hardening Script # Generated via https://infracalc.web.id # ===================================================================== set -euo pipefail echo "[1/4] Configuring UFW Default Policies..." sudo ufw default deny incoming sudo ufw default allow outgoing echo "[2/4] Allowing SSH Port (22/tcp)..." sudo ufw allow 22/tcp comment 'SSH Management' echo "[3/4] Zero-Trust Cloudflare Tunnel Active: Blocking public HTTP/HTTPS direct ports..." # No inbound 80/443 needed on public VPS IP when using cloudflared! echo "[4/4] Enabling UFW & Verifying Database Isolation (db-net internal: true)..." sudo ufw --force enable sudo ufw status verbose
# .env.example ā Copy to .env before running 'docker compose up -d' DB_NAME=kampus_app_db DB_USER=kampus_app_user DB_PASSWORD=ChangeMe_StrongPassword_2026! DB_ROOT_PASSWORD=ChangeMe_RootSecret_2026! REDIS_PASSWORD=ChangeMe_RedisSecret_2026! CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoi...paste_your_tunnel_token_here
How to Use This Tool
- Define project slug, production target domain, and custom Linux VPS SSH management port.
- Select components across the 4 architecture tiers: Edge Ingress, Frontend UI, Backend API Engine, and Database & Cache Add-ons.
- Inspect the live interactive SVG topology diagram, then copy or download the generated docker-compose.yml, nginx.conf, and setup-firewall.sh scripts.
Worked Example: Campus App (Full-Stack Next.js + Laravel + Postgres + Redis)
Architecture example: Project 'siakad-kampus' targeting 'siakad.univ.ac.id' with Hybrid Nginx + Cloudflare Tunnel, Next.js SSR (:3000), Laravel Octane (:8000), PostgreSQL 16 (:5432), Redis 7 (:6379), and Uptime Kuma (:3001) provisions 7 containers using ~2.1 GB RAM on a 4 GB / 2 vCPU VPS.
- Project Name (Slug)
- Siakad Kampus
- Production Domain
- siakad.univ.ac.id
- Edge Ingress & Proxy Tier
- Hybrid Nginx + Cloudflare Tunnel (Double Protection)
- Frontend UI Tier
- Next.js SSR Frontend (Node 20, Port 3000)
- Backend API Engine Tier
- Laravel PHP 8.3 Octane / FrankenPHP (Port 8000)
- Isolated Database Tier
- PostgreSQL 16 Relational DB (Port 5432 Internal)
- Enable Redis 7.4 In-Memory Cache (:6379)
- Yes / Active
- Enable Uptime Kuma Health Monitoring (:3001)
- Yes / Active
- VPS SSH Port for UFW Firewall
- 2,222
- Stack Project Name
- siakad-kampus
- Production Target Domain
- siakad.univ.ac.id
- Total Active Containers
- 7 Containers
- Estimated RAM Memory Usage
- 1872 MB
- Recommended VPS Specification
- 4 vCPU / 4 GB RAM
- Security Posture & Isolation
- ZERO-TRUST TUNNEL (0 Port Web Terbuka di IP Publik + DB Terisolasi)
- Material Requirement Summary (Copy-Ready)
- # ===================================================================== # Generated by InfraCalc Visual Stack Composer (https://infracalc.web.id) # Project : siakad-kampus (siakad.univ.ac.id) # Topology: BOTH_NGINX_AND_CF -> frontend + backend-api -> POSTGRES_16 + redis # ===================================================================== name: siakad-kampus services: nginx-proxy: image: nginx:1.27-alpine container_name: siakad-kampus-nginx restart: unless-stopped ports: - "127.0.0.1:8080:80" volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro - ./certbot/conf:/etc/letsencrypt:ro depends_on: - frontend - backend-api networks: - edge-net cloudflared: image: cloudflare/cloudflared:latest container_name: siakad-kampus-tunnel restart: unless-stopped command: tunnel --no-autoupdate run environment: TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN} networks: - edge-net frontend: image: node:20-alpine container_name: siakad-kampus-frontend restart: unless-stopped working_dir: /app environment: NODE_ENV: production NEXT_PUBLIC_API_URL: https://siakad.univ.ac.id/api expose: - "3000" networks: - edge-net backend-api: image: dunglas/frankenphp:1-php8.3-alpine container_name: siakad-kampus-backend restart: unless-stopped working_dir: /app command: php artisan octane:frankenphp --host=0.0.0.0 --port=8000 environment: APP_ENV: production PORT: 8000 DB_HOST: database DB_PORT: 5432 DB_NAME: ${DB_NAME:-app_db} DB_USER: ${DB_USER:-app_user} DB_PASSWORD: ${DB_PASSWORD} REDIS_URL: redis://redis-cache:6379 expose: - "8000" depends_on: database: condition: service_healthy networks: - edge-net - db-net database: image: postgres:16-alpine container_name: siakad-kampus-db restart: unless-stopped environment: POSTGRES_DB: ${DB_NAME:-app_db} POSTGRES_USER: ${DB_USER:-app_user} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-app_user} -d ${DB_NAME:-app_db}"] interval: 10s timeout: 5s retries: 5 networks: - db-net redis-cache: image: redis:7.4-alpine container_name: siakad-kampus-redis restart: unless-stopped command: redis-server --save 60 1 --loglevel warning --requirepass ${REDIS_PASSWORD} volumes: - redis-data:/data networks: - db-net uptime-kuma: image: louislam/uptime-kuma:1 container_name: siakad-kampus-monitoring restart: unless-stopped ports: - "127.0.0.1:3001:3001" volumes: - kuma-data:/app/data networks: - edge-net networks: edge-net: driver: bridge db-net: driver: bridge internal: true volumes: db-data: redis-data: kuma-data:
- Nginx Reverse Proxy Configuration (nginx.conf)
- # ===================================================================== # Nginx Reverse Proxy Configuration ā Generated via https://infracalc.web.id # Domain: siakad.univ.ac.id # ===================================================================== upstream frontend_upstream { server frontend:3000; keepalive 32; } upstream backend_upstream { server backend-api:8000; keepalive 32; } server { listen 80; server_name siakad.univ.ac.id; # Security Headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; client_max_body_size 25M; # Backend API Route (/api/* -> backend-api:8000) location /api/ { proxy_pass http://backend_upstream; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Root Route (-> frontend:3000) location / { proxy_pass http://frontend_upstream; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
- Linux Script
- #!/usr/bin/env bash # ===================================================================== # Ubuntu/Debian VPS & Docker Firewall Hardening Script # Generated via https://infracalc.web.id # ===================================================================== set -euo pipefail echo "[1/4] Configuring UFW Default Policies..." sudo ufw default deny incoming sudo ufw default allow outgoing echo "[2/4] Allowing SSH Port (2222/tcp)..." sudo ufw allow 2222/tcp comment 'SSH Management' echo "[3/4] Zero-Trust Cloudflare Tunnel Active: Blocking public HTTP/HTTPS direct ports..." # No inbound 80/443 needed on public VPS IP when using cloudflared! echo "[4/4] Enabling UFW & Verifying Database Isolation (db-net internal: true)..." sudo ufw --force enable sudo ufw status verbose
- Environment Variables Template (.env.example)
- # .env.example ā Copy to .env before running 'docker compose up -d' DB_NAME=siakad_kampus_db DB_USER=siakad_kampus_user DB_PASSWORD=ChangeMe_StrongPassword_2026! DB_ROOT_PASSWORD=ChangeMe_RootSecret_2026! REDIS_PASSWORD=ChangeMe_RedisSecret_2026! CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoi...paste_your_tunnel_token_here
| Container Service Name | Service Role | Docker Image Base | Container Internal Port | Public WAN Exposure | Estimated RAM |
|---|---|---|---|---|---|
| nginx-proxy | Edge Reverse Proxy & SSL Termination | nginx:1.27-alpine | 80, 443 | 127.0.0.1:8080 (Local/Tunnel) | 96 MB |
| cloudflared | Zero-Trust Outbound Tunnel (Zero Open Inbound Port) | cloudflare/cloudflared:latest | Outbound QUIC/HTTP2 | TERTUTUP (0 Port Terbuka di IP Publik VPS) | 80 MB |
| frontend | Next.js SSR Frontend | node:20-alpine | 3000/tcp | Internal Only (stack-net) | 384 MB |
| backend-api | Laravel PHP 8.3 (Octane/FrankenPHP) | dunglas/frankenphp:1-php8.3-alpine | 8000/tcp | Internal Only (stack-net) | 512 MB |
| database | PostgreSQL 16 Relational DB | postgres:16-alpine | 5432/tcp | Terisolasi penuh di db-net (Tanpa Port Publik) | 512 MB |
| redis-cache | Redis 7 In-Memory Cache & Session Store | redis:7.4-alpine | 6379/tcp | Terisolasi penuh di db-net | 128 MB |
| uptime-kuma | Uptime Kuma Status & Health Monitor | louislam/uptime-kuma:1 | 3001/tcp | 127.0.0.1:3001 (Internal/Tunnel) | 160 MB |
Core Concept & Engineering Notes
How It Was Calculated (Formulas & Steps)
Mathematical Formulas
- Total Stack RAM (MB) = Σ(RAM Ingress + RAM Frontend + RAM Backend + RAM Database + RAM Addons)
- Recommended VPS RAM = Total Stack RAM <= 1.2 GB ? 2 GB : Total Stack RAM <= 2.6 GB ? 4 GB : 8 GB
- Network Isolation = db-net { driver: bridge, internal: true } -> 0 Exposed WAN Ports
Frequently Asked Questions (FAQ)
Why must database containers reside in an internal network without host port binding?
Binding ports 5432 or 3306 directly to the host exposes databases to public internet brute-force attacks and zero-day exploits. Defining internal: true ensures databases are only reachable by backend containers on the shared private bridge network.
What are the advantages of a Hybrid Nginx + Cloudflare Zero-Trust Tunnel architecture?
Cloudflare Tunnel conceals the VPS public IP completely with zero open inbound firewall ports, while local Nginx handles microservice path routing (/api/*), gzip/brotli compression, and local caching.
What is the recommended minimum VPS RAM to run this complete Docker stack?
For a standard production stack (Nginx + Next.js + Backend API + Database + Redis), a VPS with at least 2 GB to 4 GB RAM and 2 GB Linux Swap is recommended to prevent OOM Killer termination during traffic spikes.
Related Calculators
View All Linux & DevOps Tools āGenerate production Linux server firewall rulesets for UFW, iptables, and /etc/nftables.conf with SSH rate-limiting and trusted subnet whitelisting.
Calculate optimal Linux swap size, vm.swappiness, vm.vfs_cache_pressure sysctl tunables, default ext4 inode count, and /swapfile creation script.
Calculate physical CPU cores, host RAM sizing with ZFS ARC cache buffer for Proxmox/ESXi, and network backup data transfer duration (RTO).
Convert Linux chmod octal (755, 644, 4750) and symbolic (-rwxr-xr-x) permissions, calculate umask, audit 777 security risks, and view breakdown tables.
References & Notes
- Docker Compose Specification ā Networking & Service Isolation
- Nginx Reverse Proxy Documentation & Upstream Keepalive Tuning
- Cloudflare Zero Trust Tunnel Architecture Guide
Note: Results above are mathematical estimates based on standard formulas. Always verify against official vendor documentation and site conditions before production deployment.
Engineering Sensitivity Analysis, Response Curve & Technical Citation
1. 1. 3-Point Engineering Sensitivity & Tolerance Envelope
Comparative evaluation across theoretical laboratory bounds (0% loss), current nominal operating point, and conservative field safety bounds (±15% thermal/aging derating).
| Evaluated Parameter | Ideal Theoretical Bound | Nominal Operating Point | Conservative Safety Bound (±15%) | Engineering Derating Rule |
|---|---|---|---|---|
| Total Active Containers | 6.3 | 7 | 8.05 | Engineering Safety Margin (+15% Overhead) |
| Estimated RAM Memory Usage | 1,685 MB | 1,872 MB | 2,153 MB | Engineering Safety Margin (+15% Overhead) |
2. 2. Mathematical Function Curve & Operating Coordinate (xā, yā)
3. 3. Physical Constants & Normative Standard Clauses
DC Loop Resistance for 23 AWG Solid Copper Cat6
Clause 6.4.1 / Table 145-1 ā Nominal 23 AWG solid copper loop resistance at 20°C is 14.0 Ī©/100m (TIA maximum ceiling is 18.8 Ī©/100m).
Single-Mode Optical Fiber Attenuation Coefficient at 1490 nm
Table 1 / Class B+ & C+ Optical Path ā Typical G.652.D attenuation at 1490 nm downstream is 0.22ā0.25 dB/km (1310 nm upstream: 0.35 dB/km).
Temperature Coefficient of Resistance for Copper
International Annealed Copper Standard ā Used in thermal derating equation: R(T) = R_20 Ć [1 + 0.00393 Ć (T - 20)].
4. 4. Independent Technical & Academic Citation (IEEE / APA 7th / BibTeX / LaTeX)
Use the standard citation formats below to reference this computational methodology in engineering specifications, audit reports, or academic papers.
[IEEE] InfraCalc Engineering Team, "Docker, Nginx & Linux Stack Visual Composer ā Standard Engineering Computational Instrument," InfraCalc Technical Suite, 2026. [Online]. Available: https://infracalc.web.id/en/tools/docker-nginx-stack-composer. [Accessed: 2026-11-08].
[APA 7th] InfraCalc Engineering Team. (2026). Docker, Nginx & Linux Stack Visual Composer (Production release 2026-11-08) [Engineering computational software]. InfraCalc. https://infracalc.web.id/en/tools/docker-nginx-stack-composer
@software{infracalc_docker_nginx_stack_composer_2026,
author = {{InfraCalc Engineering Team}},
title = {{Docker, Nginx & Linux Stack Visual Composer --- InfraCalc Engineering Suite}},
year = {2026},
publisher = {InfraCalc.web.id},
url = {https://infracalc.web.id/en/tools/docker-nginx-stack-composer},
urldate = {2026-11-08}
}
% LaTeX Engineering Derivation ā Generated via https://infracalc.web.id/en/tools/docker-nginx-stack-composer
\begin{equation}
\text{Model: } Total Stack RAM (MB) = Σ(RAM Ingress + RAM Frontend + RAM Backend + RAM Database + RAM Addons)
\end{equation}
% Parameter Input Terukur: projectName = kampus-app, \; domainName = app.example.com, \; edgeIngress = BOTH_NGINX_AND_CF, \; frontendStack = NEXTJS_NODE
% Hasil Evaluasi Numerik : stackName = \mathbf{kampus-app}, \; targetDomain = \mathbf{app.example.com}, \; totalContainersCount = \mathbf{7}