Optimasi Caddy Reverse Proxy untuk Node.js Production di Linux VPS

Panduan lengkap konfigurasi Caddy web server sebagai reverse proxy aplikasi Node.js di Linux VPS: otomatisasi HTTPS, HTTP/3 QUIC, kompresi zstd, security headers, dan panduan pengujian beban mandiri.

Server rack data center infrastruktur Linux VPS untuk reverse proxy Caddy dan Node.js production
Photo by Lars Kienle on Unsplash

Pada panduan sebelumnya, kita sudah membahas Panduan Deploy Aplikasi Node.js di VPS Ubuntu untuk Pemula menggunakan stack klasik: PM2, Nginx, dan Certbot Let's Encrypt. Setup tersebut terbukti stabil, namun memiliki beberapa friksi operasional: konfigurasi reverse proxy yang panjang, perlunya cron job renewal sertifikat SSL terpisah, dan konfigurasi manual yang rumit jika ingin mengaktifkan protokol modern seperti HTTP/3 (QUIC).

Sebagai alternatif modern, Caddy hadir sebagai web server berbasis Go yang dirancang dengan filosofi secure-by-default dan zero-friction. Caddy mengotomatiskan penerbitan dan pembaruan sertifikat TLS, mendukung HTTP/3 secara native out-of-the-box, serta menyederhanakan konfigurasi reverse proxy menjadi beberapa baris deklaratif.

Artikel ini memandu konfigurasi production-grade Caddy untuk aplikasi Node.js di Linux VPS, lengkap dengan kompresi modern (Zstandard & Gzip), security headers, optimasi buffer, benchmark beban, serta analisis footprint memori.


Ringkasan Cepat (TL;DR)

  • Mengapa Caddy? Auto HTTPS (Let's Encrypt & ZeroSSL) tanpa Certbot, native HTTP/3 (QUIC) tanpa kompilasi ulang, auto WebSocket upgrade, dan konfigurasi ringkas.
  • Karakteristik Resource: Caddy memanfaatkan runtime Go dengan footprint memori sedikit di atas Nginx, namun mengeliminasi kompleksitas operasional sertifikat dan konfigurasi manual.
  • Protokol: Mendukung HTTP/1.1, HTTP/2, dan HTTP/3 (UDP port 443) secara simultan.
  • Kompresi: Mendukung Zstandard (zstd) dan Gzip native untuk efisiensi kompresi payload modern tanpa modul pihak ketiga.

Prasyarat Server & Aplikasi

Sebelum masuk ke konfigurasi, pastikan lingkungan VPS memenuhi kriteria berikut:

  1. Linux VPS: Ubuntu 22.04 LTS atau 24.04 LTS (minimal 1 vCPU, 1 GB RAM).
  2. Domain: Domain aktif dengan DNS A Record (dan AAAA jika IPv6 aktif) sudah mengarah ke IP publik VPS.
  3. Aplikasi Node.js Aktif: Aplikasi sudah berjalan di localhost (misal via PM2 di 127.0.0.1:3000).
  4. Firewall Port Terbuka:
    • Port 80/tcp (HTTP challenge Let's Encrypt)
    • Port 443/tcp (HTTPS / HTTP/1.1 & HTTP/2)
    • Port 443/udp (Wajib untuk HTTP/3 QUIC)

1. Caddy vs Nginx: Perbandingan Fitur untuk Node.js

Sebelum beralih, perhatikan perbedaan teknis mendasar antara Nginx dan Caddy:

Fitur Nginx Caddy v2
Bahasa & Arsitektur C (Event-driven, multi-worker) Go (Goroutines, memory-safe)
Otomatisasi SSL/TLS Butuh Certbot / cron eksternal Built-in otomatis (Let's Encrypt + ZeroSSL fallback)
Dukungan HTTP/3 (QUIC) Perlu module khusus / build Nginx mainline Native out-of-the-box
Reverse Proxy WebSocket Butuh header Upgrade & Connection manual Otomatis di-forward tanpa konfigurasi tambahan
Kompresi Modern Gzip bawaan; Brotli/zstd butuh third-party module Built-in gzip dan zstd (Zstandard)
Karakteristik Memori Sangat ramping (C worker proses) Runtime Go (goroutine & garbage collector)
Reload Konfigurasi nginx -s reload caddy reload (Zero-downtime via API internal)

Jika server Anda memiliki RAM sangat terbatas (< 512 MB), Nginx tetap menjadi juara efisiensi memori mentah. Namun pada server modern (1 GB RAM ke atas), Caddy memberikan efisiensi operasional jauh lebih tinggi tanpa risiko sertifikat SSL kedaluwarsa atau kegagalan handshake TLS seperti yang diulas pada kasus ERR_SSL_VERSION_OR_CIPHER_MISMATCH.


2. Instalasi Caddy di Linux Ubuntu

Install Caddy di Ubuntu 22.04 / 24.04 LTS melalui package repository resmi:

  1. Pasang dependensi pendukung: sudo apt install debian-keyring debian-archive-keyring apt-transport-https
  2. Tambahkan repository stable Caddy dan GPG keyring resmi sesuai panduan dokumentasi Caddy.
  3. Perbarui index paket: sudo apt update
  4. Pasang paket web server Caddy: sudo apt install caddy

Periksa status service systemd:

sudo systemctl status caddy

3. Konfigurasi Firewall (UFW) untuk HTTP/3

HTTP/3 berjalan di atas protokol UDP. Jika UFW hanya membuka port TCP, koneksi client akan fallback ke HTTP/2. Buka port TCP dan UDP sekaligus:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enable
sudo ufw status

4. Production Caddyfile untuk Node.js

File konfigurasi utama Caddy berada di /etc/caddy/Caddyfile. Buka file tersebut dengan text editor:

sudo nano /etc/caddy/Caddyfile

Hapus konfigurasi default dan gunakan konfigurasi production berikut (sesuaikan domainkamu.com dan port aplikasi):

{
    # Global options
    email admin@domainkamu.com
    admin off # Nonaktifkan admin API port 2019 jika tidak digunakan via external network
}

(security_headers) {
    header {
        # Strict Transport Security (HSTS)
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        
        # Mencegah MIME-type sniffing
        X-Content-Type-Options "nosniff"
        
        # Proteksi clickjacking
        X-Frame-Options "DENY"
        
        # Kontrol referrer info
        Referrer-Policy "strict-origin-when-cross-origin"
        
        # Batasi fitur browser yang tidak dibutuhkan
        Permissions-Policy "camera=(), microphone=(), geolocation=()"
        
        # Hapus header signature server untuk security by obscurity
        -Server
        -X-Powered-By
    }
}

domainkamu.com, www.domainkamu.com {
    # 1. Terapkan Security Headers
    import security_headers

    # 2. Aktifkan Kompresi Modern (Zstandard & Gzip)
    encode zstd gzip

    # 3. Batasi Ukuran Request Body (Mencegah serangan DoS payload besar)
    request_body {
        max_size 10MB
    }

    # 4. Logging Terstruktur (JSON Format)
    log {
        output file /var/log/caddy/domainkamu_access.log {
            roll_size 50mb
            roll_keep 5
            roll_keep_for 720h
        }
        format json
    }

    # 5. Reverse Proxy ke Node.js Backend
    reverse_proxy 127.0.0.1:3000 {
        # Health check upstream otomatis
        health_uri /health
        health_interval 15s
        health_timeout 3s

        # Buffering responses untuk kestabilan load
        header_up Host {upstream_hostport}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}

        # Timeout koneksi backend
        transport http {
            dial_timeout 5s
            response_header_timeout 30s
        }
    }
}

Validasi dan Reload Konfigurasi

Caddy memiliki syntax checker bawaan. Selalu validasi file sebelum memuat perubahan ke memori:

# Validasi sintaks Caddyfile
caddy validate --config /etc/caddy/Caddyfile

# Reload tanpa downtime (zero-downtime reload)
sudo systemctl reload caddy

5. Menangani Static Files & Cache Headers

Jika aplikasi Node.js (seperti Express, Fastify, atau Next.js) memiliki folder aset statis (public/ atau dist/), melayani aset langsung lewat Caddy jauh lebih hemat resource daripada membebankan event loop Node.js.

Tambahkan blok matcher untuk melayani file statis langsung lewat Caddy:

domainkamu.com {
    import security_headers
    encode zstd gzip

    # Sajikan aset statis langsung dengan header cache panjang
    @static {
        path /assets/* /static/* /favicon.ico /robots.txt
    }
    handle @static {
        root * /var/www/app/public
        header Cache-Control "public, max-age=31536000, immutable"
        file_server
    }

    # Semua request dinamis diarahkan ke Node.js
    handle {
        reverse_proxy 127.0.0.1:3000
    }
}

6. Panduan Pengujian Beban Mandiri & Analisis Arsitektur

Karakteristik performa reverse proxy sangat dipengaruhi oleh spesifikasi server, arsitektur aplikasi backend, ukuran payload, serta latensi jaringan. Daripada mengandalkan estimasi benchmark teoritis yang bervariasi antar lingkungan, lakukan pengujian mandiri di server Anda secara langsung.

Melakukan Stress Test Mandiri dengan Autocannon

Tool benchmarking berbasis Node.js seperti autocannon sangat praktis untuk menguji ketahanan reverse proxy terhadap beban konkurensi tinggi.

Install autocannon secara global di mesin penguji (disarankan dijalankan dari VPS terpisah atau mesin lokal agar tidak membebani CPU server target):

npm install -g autocannon

Jalankan pengujian bertahap, mulai dari beban moderat ke beban tinggi:

# Pengujian baseline: 20 koneksi konkuren selama 10 detik
autocannon -c 20 -d 10 https://domainkamu.com/api/test

# Pengujian konkurensi tinggi: 100 koneksi konkuren dengan 10 pipelining
autocannon -c 100 -d 20 -p 10 https://domainkamu.com/api/test

Metrik utama yang perlu Anda evaluasi dari output autocannon:

  • Req/Sec (Throughput): Jumlah request sukses per detik yang mampu diproses upstream Node.js via Caddy.
  • Latency (p99 / 99th percentile): Waktu respon maksimal untuk 99% request. Kenaikan p99 yang drastis mengindikasikan antrean buffer atau event loop saturation di Node.js.
  • Non-2xx / Timeouts: Memastikan tidak ada lonjakan error 502 (Bad Gateway) yang mengindikasikan koneksi Caddy ke backend putus.

Trade-off Arsitektur: Go Goroutines vs Nginx C Worker

Memahami perbedaan arsitektur Caddy dan Nginx membantu menentukan kapan masing-masing alat paling tepat digunakan:

  1. Model Konkurensi Go (Goroutines): • Caddy menggunakan goroutine runtime Go. Setiap koneksi dikelola oleh goroutine yang sangat ringan (hanya beberapa kilobyte stack memori awal). • Runtime Go menyertakan garbage collector (GC), sehingga penggunaan memori baseline (RSS) Caddy umumnya sedikit lebih tinggi dibanding server berbasis C. Namun untuk VPS modern (1 GB RAM ke atas), overhead ini tergolong kecil dibandingkan kenyamanan otomatisasi operasionalnya.
  2. Model Proses Nginx (Event-Driven C): • Nginx ditulis dalam bahasa C dengan model master-worker non-blocking berbasis epoll/kqueue. • Mengonsumsi memori mentah yang sangat minim dan deterministik tanpa jeda GC, menjadikannya pilihan ideal untuk server resource-constrained ekstrem (< 512 MB RAM) atau static edge serving skala raksasa.
  3. Kompresi Zstandard (zstd): • Caddy menyertakan algoritma Zstandard out-of-the-box bersama Gzip. Algoritma zstd dirancang untuk memberikan rasio kompresi tinggi dengan kecepatan dekompresi mendekati batas memori hardware. Client modern yang mendukung header Accept-Encoding: zstd otomatis menerima payload yang lebih ringkas tanpa perlu instalasi module third-party.

Memantau Penggunaan Memori Real-Time

Untuk mengamati konsumsi RAM proses Caddy selama pengujian beban berlangsung:

# Pantau konsumsi memori resident (RSS) Caddy
ps -C caddy -o pid,comm,%cpu,%mem,rss,vsz

7. Integrasi Monitoring Server

Format log JSON yang dihasilkan oleh Caddy memudahkan integrasi dengan pipeline observabilitas server. Anda dapat mengalirkan log Caddy ke Prometheus dan Grafana seperti yang dijelaskan pada artikel Cara Setup Monitoring Server Murah Pakai Grafana + Prometheus.

Untuk mengaktifkan Prometheus metrics endpoint internal di Caddy:

{
    servers {
        metrics
    }
}

Metrics Prometheus Caddy kini tersedia secara internal di port http://localhost:2019/metrics untuk di-scrape oleh Prometheus Node Exporter.


FAQ (Pertanyaan yang Sering Diajukan)

Apa perbedaan utama Caddy dan Nginx untuk Node.js?

Perbedaan utama terletak pada otomatisasi SSL/TLS dan HTTP/3. Caddy mengelola penerbitan, instalasi, dan perpanjangan sertifikat TLS secara otomatis tanpa dependensi Certbot eksternal, mendukung HTTP/3 (QUIC) secara native, dan memiliki sintaks konfigurasi deklaratif yang jauh lebih ringkas dibanding Nginx.

Apakah Caddy aman digunakan untuk produksi traffic tinggi?

Ya. Caddy v2 ditulis dengan Go modern yang mengimplementasikan memory-safety, goroutines yang sangat efisien untuk menangani ribuan koneksi konkuren, serta telah digunakan secara luas oleh platform cloud seperti Cloudflare, Render, dan Pulumi untuk edge proxying.

Mengapa HTTP/3 di Caddy tidak terdeteksi oleh browser?

Pastikan port 443/udp terbuka di firewall VPS (sudo ufw allow 443/udp) dan security group cloud provider. Browser modern juga memerlukan header Alt-Svc pada response HTTPS pertama untuk mendeteksi ketersediaan HTTP/3, yang secara otomatis diinjeksi oleh Caddy.

Bagaimana cara reload Caddyfile tanpa downtime?

Jalankan perintah sudo systemctl reload caddy atau caddy reload --config /etc/caddy/Caddyfile. Caddy akan memverifikasi konfigurasi baru di latar belakang, memuat konfigurasi baru, dan menghentikan worker lama secara graceful tanpa memutus koneksi aktif.


Kesimpulan

Bagi pengembang yang mengelola VPS mandiri, Caddy adalah evolusi natural dari reverse proxy web server tradisional. Dengan mengganti Nginx ke Caddy, Anda mengeliminasi kompleksitas cron job Certbot, mendapatkan proteksi HTTPS otomatis, dan langsung menikmati kecepatan HTTP/3 serta kompresi Zstandard tanpa konfigurasi berbelit.

Langkah berikutnya setelah reverse proxy stabil adalah melengkapi server dengan monitoring Prometheus dan Grafana untuk mengawasi latensi request dan utilisasi RAM server secara berkala.