Aplikasi Express.js sudah berjalan di lokal — sekarang saatnya deploy ke server production. Di artikel penutup seri Express.js ini, kita bahas cara deploy yang benar: menggunakan PM2 sebagai process manager, mengatur environment variables dengan aman, dan konfigurasi Nginx sebagai reverse proxy.
Apa yang Berubah di Production?
Beberapa hal yang berbeda antara development dan production:
| Aspek | Development | Production |
|---|---|---|
NODE_ENV |
development |
production |
| Error messages | Detail + stack trace | Pesan umum saja |
| Logging | Verbose | Structured, ke file |
| Restart otomatis | nodemon | PM2 |
| HTTPS | Tidak wajib | Wajib |
| Port | 3000 | 80/443 via Nginx |
Menyiapkan Kode untuk Production
1. Gunakan Environment Variables
Jangan hardcode konfigurasi sensitif. Gunakan file .env untuk development dan env variable server untuk production.
npm install dotenv
.env (jangan dicommit ke Git!):
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://user:pass@localhost/dbname
JWT_SECRET=ganti-dengan-string-acak-panjang
CORS_ORIGIN=https://frontend.namakamu.com
index.js — muat di baris pertama:
require('dotenv').config();
const express = require('express');
// ...
Tambahkan .env ke .gitignore:
.env
node_modules/
2. Konfigurasi CORS yang Tepat
const cors = require('cors');
const corsOptions = {
origin: process.env.NODE_ENV === 'production'
? process.env.CORS_ORIGIN
: '*',
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
};
app.use(cors(corsOptions));
3. Aktifkan Helmet untuk Keamanan HTTP Headers
const helmet = require('helmet');
app.use(helmet());
Helmet otomatis mengatur header seperti X-Content-Type-Options, X-Frame-Options, Content-Security-Policy, dan lainnya.
4. Script di package.json
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"prod": "NODE_ENV=production node index.js"
}
}
PM2 — Process Manager untuk Node.js
PM2 memastikan aplikasi Node.js kamu tetap berjalan — restart otomatis saat crash, start saat server reboot, load balancing multi-core, dan monitoring bawaan.
Instalasi PM2
npm install -g pm2
Konfigurasi PM2
Buat file ecosystem.config.js di root project:
module.exports = {
apps: [{
name: 'api-express',
script: 'index.js',
instances: 'max', // gunakan semua CPU core
exec_mode: 'cluster', // mode cluster untuk load balancing
watch: false, // jangan watch di production
max_memory_restart: '500M',
env_production: {
NODE_ENV: 'production',
PORT: 3000
},
log_file: './logs/combined.log',
error_file: './logs/error.log',
out_file: './logs/out.log',
time: true // tambahkan timestamp di log
}]
};
Perintah PM2
# Mulai aplikasi
pm2 start ecosystem.config.js --env production
# Lihat status
pm2 status
pm2 list
# Monitor real-time
pm2 monit
# Lihat log
pm2 logs api-express
pm2 logs api-express --lines 100
# Restart
pm2 restart api-express
# Reload (zero-downtime restart)
pm2 reload api-express
# Stop
pm2 stop api-express
# Auto-start saat server reboot
pm2 startup
pm2 save
Nginx sebagai Reverse Proxy
Jangan ekspos Node.js langsung ke internet. Gunakan Nginx sebagai reverse proxy — Nginx menerima request di port 80/443 dan meneruskan ke Node.js di port 3000.
Konfigurasi Nginx
/etc/nginx/sites-available/api-express:
server {
listen 80;
server_name api.namakamu.com;
# Redirect ke HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name api.namakamu.com;
ssl_certificate /etc/letsencrypt/live/api.namakamu.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.namakamu.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
# Limit ukuran upload
client_max_body_size 10M;
location / {
proxy_pass http://localhost:3000;
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;
proxy_cache_bypass $http_upgrade;
}
# Cache static files
location /uploads {
alias /var/www/api-express/uploads;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
# Aktifkan konfigurasi
sudo ln -s /etc/nginx/sites-available/api-express /etc/nginx/sites-enabled/
sudo nginx -t # test konfigurasi
sudo systemctl reload nginx
Install SSL dengan Certbot
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d api.namakamu.com
Certbot akan otomatis memperbarui sertifikat SSL setiap 90 hari.
Proses Deployment
# Di server, clone project
git clone https://github.com/username/api-express.git
cd api-express
# Install dependencies (tanpa devDependencies)
npm install --omit=dev
# Set environment variables
cp .env.example .env
nano .env # edit sesuai konfigurasi server
# Jalankan migrasi database (jika pakai Prisma)
npx prisma migrate deploy
# Start dengan PM2
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup
Update Deployment (CI/CD Manual)
git pull origin main
npm install --omit=dev
npx prisma migrate deploy # jika ada migrasi baru
pm2 reload api-express # zero-downtime reload
Checklist Production
NODE_ENV=productionsudah diset- Semua secret di environment variable, tidak di kode
.envtidak dicommit ke Git- HTTPS aktif dengan sertifikat SSL valid
- Nginx dikonfigurasi sebagai reverse proxy
- PM2 berjalan dengan mode cluster
- PM2 diset auto-start saat reboot (
pm2 startup && pm2 save) - Logging ke file (
pm2 logs) - Rate limiting aktif
- Helmet.js aktif
Kesimpulan
Deploy Express.js ke production bukan sekadar node index.js — ada lapisan keamanan, keandalan, dan performa yang perlu disiapkan. Dengan PM2 + Nginx + HTTPS, aplikasi Express.js kamu siap melayani trafik production dengan stabil dan aman.
Dengan ini, seri tutorial Express.js kita selesai — mulai dari instalasi dasar, routing, middleware, request/response, REST API, database, autentikasi JWT, error handling, upload file, hingga deployment production. Selamat membangun API!
Kiki/🎮🍉⌨️🍩💻