Konsep Reverse Proxy

Konsep Reverse Proxy #

Reverse proxy adalah komponen infrastruktur yang menerima request dari client dan meneruskannya ke satu atau lebih server backend atas nama client tersebut. Dari perspektif client, mereka hanya berkomunikasi dengan satu server — proxy. Backend tersembunyi di balik proxy, dan client tidak perlu mengetahui arsitektur internal sama sekali.

Ini adalah pola arsitektur yang sangat umum di deployment modern, dan Caddy mengimplementasikannya dengan cara yang sangat elegan — menjadikannya salah satu reverse proxy paling mudah dikonfigurasi tanpa mengorbankan fitur.

Forward Proxy vs Reverse Proxy #

Kedua istilah ini sering membingungkan. Perbedaan mendasarnya adalah dari perspektif siapa proxy tersebut bekerja:

Forward Proxy (proxy biasa):
  Client → [Forward Proxy] → Internet

  - Client dikonfigurasi untuk menggunakan proxy
  - Proxy mewakili CLIENT
  - Server tujuan tidak tahu client yang sebenarnya
  - Contoh: corporate proxy, VPN, Tor

Reverse Proxy:
  Client → [Reverse Proxy] → Backend Server

  - Client tidak tahu ada proxy (transparan)
  - Proxy mewakili SERVER
  - Client hanya tahu alamat proxy, tidak tahu backend
  - Contoh: Caddy, Nginx, HAProxy di depan aplikasi

Mengapa Menggunakan Reverse Proxy? #

1. Terminasi TLS #

Salah satu alasan paling umum: mengizinkan aplikasi backend berjalan tanpa TLS (HTTP biasa) sementara client tetap mendapat koneksi HTTPS yang aman.

Tanpa reverse proxy:
  Client ──HTTPS──► App (harus handle TLS sendiri)
  
  Masalah:
  - Setiap aplikasi perlu konfigurasi TLS terpisah
  - Sertifikat tersebar di banyak tempat
  - Renewal sertifikat harus di-manage per-aplikasi
  - Node.js, Python, Java — semua butuh konfigurasi TLS berbeda

Dengan reverse proxy (TLS termination):
  Client ──HTTPS──► Caddy ──HTTP──► App (simple, no TLS)
  
  Keuntungan:
  - TLS dikelola di satu tempat (Caddy)
  - Backend hanya perlu handle HTTP biasa
  - Otomatis renewal sertifikat
  - Perubahan TLS policy tidak perlu menyentuh aplikasi

2. Load Balancing #

Client ──► Caddy ──► App Instance 1 (port 3001)
                ──► App Instance 2 (port 3002)
                ──► App Instance 3 (port 3003)

Traffic didistribusikan — satu instance down tidak mempengaruhi keseluruhan

3. Path-based Routing #

example.com/api/*    ──► Backend API (Node.js :8080)
example.com/app/*    ──► Frontend SPA (port :3000)
example.com/*   ──► Documentation (Nginx :4000)
example.com/static/* ──► CDN / file server

4. Keamanan #

- Backend tidak perlu exposed ke internet langsung
- Firewall hanya perlu izinkan koneksi ke Caddy
- Rate limiting, IP blocking di lapisan proxy
- DDoS mitigation lebih mudah di satu titik
- Sembunyikan teknologi stack dari client

5. Observability #

- Access logging terpusat di satu tempat
- Metrics traffic lintas semua backend
- Tracing request dari entry point

Arsitektur Deployment yang Umum #

Single Server #

┌─────────────────────────────────────┐
│ Server                              │
│                                     │
│  ┌─────────┐     ┌──────────────┐   │
│  │  Caddy  │────►│ App (3000)   │   │
│  │  :80    │     └──────────────┘   │
│  │  :443   │     ┌──────────────┐   │
│  │         │────►│ API (8080)   │   │
│  └─────────┘     └──────────────┘   │
│       ▲          ┌──────────────┐   │
│       │          │ Database     │   │
└───────┼──────────┴──────────────┘   │
        │
     Internet

Multi-Server #

         Internet
            │
        ┌───▼───┐
        │ Caddy │  (Edge / Public server)
        │  :443 │
        └───┬───┘
            │ Private Network
    ┌───────┼───────────┐
    │       │           │
┌───▼───┐ ┌─▼──┐  ┌────▼──┐
│ App-1 │ │App2│  │ DB    │
└───────┘ └────┘  └───────┘

Containerized (Docker Compose) #

Internet → Caddy(:443) → app-container:3000
                       → api-container:8080
                       → admin-container:9000
           
           (semua container dalam satu Docker network)
           (hanya Caddy yang expose port ke host)

Alur Request Lengkap #

1. Client mengirim HTTPS request ke example.com:443
   GET /api/users HTTP/1.1
   Host: example.com
   
2. Caddy menerima koneksi, melakukan TLS handshake
   (menggunakan sertifikat Let's Encrypt yang dikelolanya)
   
3. Caddy decrypt request
   
4. Caddy mencocokkan request dengan routing rules di Caddyfile
   → Path /api/* cocok dengan rule reverse_proxy ke localhost:8080
   
5. Caddy membuat koneksi baru ke backend (localhost:8080)
   dan meneruskan request:
   GET /api/users HTTP/1.1
   Host: localhost:8080              (atau disesuaikan)
   X-Forwarded-For: 203.0.113.1     (IP client asli)
   X-Forwarded-Proto: https          (protokol asli)
   X-Real-IP: 203.0.113.1
   
6. Backend memproses request dan mengembalikan response:
   HTTP/1.1 200 OK
   Content-Type: application/json
   {"users": [...]}
   
7. Caddy menerima response dari backend
   
8. Caddy meneruskan response ke client
   (mungkin menambah/mengubah beberapa header)
   
9. Client menerima response

Connection Management #

Caddy mengelola connection pooling ke backend — ini sangat penting untuk performa:

Tanpa connection pooling (naive):
  Request 1 → [buat koneksi baru] → Backend → [tutup koneksi]
  Request 2 → [buat koneksi baru] → Backend → [tutup koneksi]
  Request 3 → [buat koneksi baru] → Backend → [tutup koneksi]
  
  Overhead: TCP handshake + TLS handshake per request = lambat

Dengan connection pooling (Caddy):
  Request 1 → [buat koneksi] → Backend (koneksi tetap terbuka)
  Request 2 → [pakai koneksi yang ada] → Backend (cepat)
  Request 3 → [pakai koneksi yang ada] → Backend (cepat)
  
  Connection pool dikelola otomatis oleh Caddy

Caddy menggunakan HTTP/1.1 persistent connections (Keep-Alive) dan HTTP/2 untuk koneksi ke backend, tergantung kapabilitas backend.


Sticky Sessions vs Stateless #

Untuk aplikasi yang menyimpan state session di memori (bukan di database/Redis):

# Tanpa sticky session (default, round-robin)
app.example.com {
    reverse_proxy backend-1:3000 backend-2:3000 backend-3:3000
    # Request bisa ke backend mana saja — session di memori akan hilang
    # jika user di-route ke backend berbeda
}

# Dengan sticky session (ip_hash)
app.example.com {
    reverse_proxy backend-1:3000 backend-2:3000 backend-3:3000 {
        lb_policy ip_hash
        # User dengan IP yang sama selalu ke backend yang sama
    }
}

# Dengan sticky session via cookie (lebih akurat)
app.example.com {
    reverse_proxy backend-1:3000 backend-2:3000 backend-3:3000 {
        lb_policy cookie {
            name caddy_backend
        }
    }
}

Caddy vs Nginx sebagai Reverse Proxy #

Aspek              Caddy                           Nginx
──────────────────────────────────────────────────────────────────
TLS               Otomatis, zero config            Manual atau via Certbot
Konfigurasi       Caddyfile (simpel, readable)     nginx.conf (verbose, syntax ketat)
Reload            Zero-downtime, graceful           Perlu test + reload manual
Load balancing    Round-robin, random, ip_hash      Round-robin, ip_hash, least_conn
Health check      Built-in aktif & pasif            Aktif hanya di Nginx Plus (berbayar)
HTTP/3            Built-in (QUIC)                  Eksperimental / perlu modul
Admin API         REST API built-in                 Tidak ada (perlu reload config)
Plugin/module     xcaddy (compile-time)             Modul dinamis (runtime)
Performa          Setara (Go vs C)                 Sedikit lebih tinggi pada high load
Ekosistem         Lebih baru, berkembang            Lebih matang, dokumentasi lebih luas

Kapan Caddy Adalah Pilihan Terbaik #

Caddy sangat cocok sebagai reverse proxy ketika:

✓ Kamu ingin HTTPS otomatis tanpa setup manual
✓ Tim kamu tidak familiar dengan konfigurasi Nginx yang verbose
✓ Kamu butuh reload konfigurasi yang benar-benar zero-downtime
✓ Kamu butuh Admin API untuk mengubah config secara programatik
✓ Environment containerized (Docker, Kubernetes)
✓ Wildcard certificate dengan DNS challenge
✓ Development environment lokal dengan HTTPS yang valid

Ringkasan #

  • Reverse proxy menerima request dari client dan meneruskannya ke backend — client tidak tahu struktur internal di balik proxy.
  • Manfaat utama: TLS termination (backend tidak perlu handle HTTPS), load balancing, routing berbasis path/host, dan keamanan (backend tersembunyi dari internet).
  • Caddy mengelola connection pooling ke backend secara otomatis — penting untuk performa di traffic tinggi.
  • Untuk aplikasi yang menyimpan session di memori, gunakan sticky sessions (lb_policy ip_hash atau cookie) agar user selalu diarahkan ke backend yang sama.
  • Caddy unggul dibanding Nginx sebagai reverse proxy terutama dalam hal HTTPS otomatis, konfigurasi yang lebih sederhana, dan built-in Admin API.

← Sebelumnya: Error Pages   Berikutnya: Konfigurasi Reverse Proxy →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact