Visual Composer Docker, Nginx & Linux Stack
Rancang arsitektur server produksi modular (Lego Builder): pilih Nginx/Cloudflare, Frontend, Backend, DB & Redis. Hasilkan topologi SVG, docker-compose.yml, dan UFW hardening otomatis.
Parameter Input
Hasil Perhitungan
- Nama Proyek Stack
- kampus-app
- Domain Target Produksi
- app.example.com
- Jumlah Kontainer Aktif
- 7 Kontainer
- Estimasi Penggunaan Memori RAM
- 1872 MB
- Rekomendasi Spesifikasi VPS
- 4 vCPU / 4 GB RAM
- Postur Keamanan & Isolasi
- ZERO-TRUST TUNNEL (0 Port Web Terbuka di IP Publik + DB Terisolasi)
Uji aturan firewall dan skrip cron pada lingkungan staging terlebih dahulu, dan simpan backup konfigurasi di Git.
| Nama Layanan Kontainer | Peran Layanan | Docker Image Base | Port Internal Kontainer | Eksposur Port Publik WAN | Estimasi 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
Cara Menggunakan Alat Ini
- Tentukan identitas proyek, domain produksi, serta port SSH kustom yang digunakan pada VPS Linux Anda.
- Pilih komponen arsitektur pada 4 lapisan: Edge Ingress, Frontend UI, Backend API, serta Database dan Add-ons (Redis / Uptime Kuma).
- Periksa diagram topologi jaringan visual SVG, lalu salin atau unduh berkas docker-compose.yml, nginx.conf, dan setup-firewall.sh untuk dieksekusi di server.
Contoh Perhitungan Nyata: Siakad Kampus (Full-Stack Next.js + Laravel + Postgres + Redis)
Contoh arsitektur: Proyek 'siakad-kampus' dengan domain 'siakad.univ.ac.id' menggunakan Hybrid Nginx + Cloudflare Tunnel, Next.js SSR (:3000), Laravel Octane (:8000), PostgreSQL 16 (:5432), Redis 7 (:6379), dan Uptime Kuma (:3001) mengaktifkan 7 kontainer dengan estimasi RAM 2.1 GB pada VPS 4 GB / 2 vCPU.
- Nama Proyek (Slug)
- Siakad Kampus
- Domain Produksi
- siakad.univ.ac.id
- Lapisan Edge & Ingress Proxy
- Hybrid Nginx + Cloudflare Tunnel (Double Protection)
- Lapisan Frontend UI / Web App
- Next.js SSR Frontend (Node 20, Port 3000)
- Lapisan Backend API Engine
- Laravel PHP 8.3 Octane / FrankenPHP (Port 8000)
- Lapisan Basis Data (Terisolasi)
- PostgreSQL 16 Relational DB (Port 5432 Internal)
- Aktifkan Redis 7.4 In-Memory Cache (:6379)
- Ya / Aktif
- Aktifkan Uptime Kuma Health Monitoring (:3001)
- Ya / Aktif
- Port SSH VPS untuk Firewall UFW
- 2.222
- Nama Proyek Stack
- siakad-kampus
- Domain Target Produksi
- siakad.univ.ac.id
- Jumlah Kontainer Aktif
- 7 Kontainer
- Estimasi Penggunaan Memori RAM
- 1872 MB
- Rekomendasi Spesifikasi VPS
- 4 vCPU / 4 GB RAM
- Postur Keamanan & Isolasi
- ZERO-TRUST TUNNEL (0 Port Web Terbuka di IP Publik + DB Terisolasi)
- Ringkasan Daftar Kebutuhan Material (Siap Salin)
- # ===================================================================== # 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:
- Konfigurasi Nginx Reverse Proxy (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
- Template Variabel Lingkungan (.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
| Nama Layanan Kontainer | Peran Layanan | Docker Image Base | Port Internal Kontainer | Eksposur Port Publik WAN | Estimasi 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 |
Konsep Dasar & Catatan Teknis
Cara Perhitungan (Rumus & Langkah)
Rumus Matematika
- Total Alokasi RAM (MB) = Σ(RAM Ingress + RAM Frontend + RAM Backend + RAM Database + RAM Addons)
- Rekomendasi RAM VPS = Total Alokasi RAM <= 1.2 GB ? 2 GB : Total Alokasi RAM <= 2.6 GB ? 4 GB : 8 GB
- Isolasi Jaringan = db-net { driver: bridge, internal: true } -> 0 Port WAN Exposed
Pertanyaan yang Sering Diajukan (FAQ)
Mengapa database (PostgreSQL/MySQL) wajib menggunakan network internal tanpa port binding ke host?
Mempublikasikan port 5432 atau 3306 ke host (misal '5432:5432') membuka celah serangan brute-force dan eksploitasi zero-day dari internet publik. Dengan network internal (internal: true), database hanya dapat diakses oleh kontainer backend di dalam VPS yang sama.
Apa keuntungan arsitektur Hybrid Nginx + Cloudflare Zero-Trust Tunnel?
Cloudflare Tunnel menyembunyikan alamat IP publik VPS secara sempurna (0 port inbound terbuka di firewall), sementara Nginx internal tetap mengelola load balancing, kompresi gzip/brotli, dan perutean path mikroservis (/api/*) secara lokal.
Berapa kapasitas RAM VPS minimum yang disarankan untuk menjalankan stack Docker komplit ini?
Untuk stack standar (Nginx + Frontend Next.js + Backend API + Database + Redis), disarankan VPS dengan minimal 2 GB hingga 4 GB RAM serta 2 GB Linux Swap untuk mencegah OOM Killer saat lonjakan trafik.
Alat Kalkulator Terkait
Lihat Semua Kalkulator Linux & DevOps āGenerate skrip hardening firewall server Linux untuk UFW, iptables, dan /etc/nftables.conf lengkap dengan proteksi rate-limit SSH dan whitelist subnet.
Hitung ukuran swap optimal Linux, parameter sysctl vm.swappiness, vm.vfs_cache_pressure, estimasi jumlah inode ext4, dan generator skrip /swapfile.
Hitung kebutuhan core CPU, RAM host hypervisor Proxmox/VMware dengan buffer ZFS ARC, serta estimasi waktu backup transfer data jaringan.
Konversi izin file Linux chmod oktal (755, 644, 4750) dan simbolik (-rwxr-xr-x), kalkulasi umask, analisis keamanan 777, dan tabel hak akses.
Referensi Standar & Catatan
- Docker Compose Specification ā Networking & Service Isolation
- Nginx Reverse Proxy Documentation & Upstream Keepalive Tuning
- Cloudflare Zero Trust Tunnel Architecture Guide
Catatan: Hasil di atas merupakan estimasi berdasarkan rumus standar. Selalu verifikasi dengan dokumentasi resmi vendor dan kondisi lapangan sebelum implementasi pada lingkungan produksi.
Analisis Sensitivitas Rekayasa, Kurva Karakteristik & Sitasi Teknis
1. Matriks Analisis Sensitivitas & Rentang Toleransi 3-Kondisi (Matriks Toleransi 3 Titik Desain)
Evaluasi perbandingan antara batas teoretis laboratorium (0% rugi-rugi), titik operasional nominal saat ini, dan batas konservatif lapangan (termasuk derating suhu konduktor, penuaan komponen, serta margin keamanan ±15%).
| Parameter Terukur | Kondisi Ideal Teoretis | Titik Kerja Operasional (Nominal) | Batas Konservatif (Worst-Case ±15%) | Kaidah Koreksi Rekayasa |
|---|---|---|---|---|
| Jumlah Kontainer Aktif | 6,3 | 7 | 8,05 | Safety Margin Kapasitas (+15% Overhead) |
| Estimasi Penggunaan Memori RAM | 1.685 MB | 1.872 MB | 2.153 MB | Safety Margin Kapasitas (+15% Overhead) |
2. Kurva Karakteristik Rekayasa, Fungsi & Titik Operasi (xā, yā)
3. Konstanta Fisika & Klausul Standar Normatif
Resistansi Loop DC Konduktor Tembaga Murni Cat6 (23 AWG)
Clause 6.4.1 / Table 145-1 ā Nilai nominal tipikal 23 AWG tembaga murni pada 20°C adalah 14.0 Ī©/100m (batas plafon standar TIA adalah 18.8 Ī©/100m).
Koefisien Atenuasi Serat Optik Single-Mode pada 1490 nm
Table 1 / Class B+ & C+ Optical Path ā Atenuasi tipikal serat G.652.D pada panjang gelombang downstream 1490 nm adalah 0.22ā0.25 dB/km (upstream 1310 nm: 0.35 dB/km).
Koefisien Suhu Resistansi Tembaga Murni
International Annealed Copper Standard ā Digunakan pada koreksi suhu: R(T) = R_20 Ć [1 + 0.00393 Ć (T - 20)].
4. Kutipan Referensi Teknis & Akademik Independen (IEEE / APA 7th / BibTeX / LaTeX)
Gunakan format sitasi standar di bawah ini untuk melampirkan metodologi perhitungan ke dalam dokumen spesifikasi teknis, laporan audit, karya ilmiah, atau jurnal rekayasa.
[IEEE] InfraCalc Engineering Team, "Visual Composer Docker, Nginx & Linux Stack ā Instrumen Komputasi & Verifikasi Standar Teknis," InfraCalc Technical Suite, 2026. [Online]. Tersedia: https://infracalc.web.id/id/tools/docker-nginx-stack-composer. [Diakses: 2026-11-08].
[APA 7th] InfraCalc Engineering Team. (2026). Visual Composer Docker, Nginx & Linux Stack (Rilis Produksi 2026-11-08) [Perangkat lunak komputasi teknik]. InfraCalc. https://infracalc.web.id/id/tools/docker-nginx-stack-composer
@software{infracalc_docker_nginx_stack_composer_2026,
author = {{InfraCalc Engineering Team}},
title = {{Visual Composer Docker, Nginx & Linux Stack --- InfraCalc Engineering Suite}},
year = {2026},
publisher = {InfraCalc.web.id},
url = {https://infracalc.web.id/id/tools/docker-nginx-stack-composer},
urldate = {2026-11-08}
}
% LaTeX Engineering Derivation ā Generated via https://infracalc.web.id/id/tools/docker-nginx-stack-composer
\begin{equation}
\text{Model: } Total Alokasi 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}