BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

Peta Cepat: Pilih yang ManaKonsep Inti Reverse Proxynginx: Routing Dasarnginx: TLS dengan ACMEnginx: Load Balancing dan UpstreamCaddy: Reverse Proxy dalam Tiga BarisCaddy: Load Balancing dan Health CheckTraefik: Routing via Label DockerTraefik: MiddlewareHeader yang Wajib Kamu PahamiPerforma dan TuningDebugging Saat Routing BerantakanChecklist ProductionGlossary
nginxCaddyTraefikDevOpsNetworking

Reverse Proxy Cheat Sheet: nginx, Caddy, Traefik

Referensi cepat reverse proxy. Routing, TLS/ACME, load balancing, header, dan tuning performa di nginx, Caddy, dan Traefik. Perfect buat DevOps.

Nginx11 min read2.126 kata
Silakan login atau daftar untuk membaca cheat sheet ini.

#Peta Cepat: Pilih yang Mana

Ketiga tool ini menyelesaikan masalah yang sama (terima trafik masuk, teruskan ke backend) dengan filosofi konfigurasi yang beda jauh. Pilih berdasarkan situasimu, bukan popularitas.

AspeknginxCaddyTraefik
Gaya configfile statis manualCaddyfile singkatlabel Docker + file dynamic
TLS/ACMElewat certbot eksternalotomatis bawaanotomatis via certificatesResolver
Service discoverymanual (edit upstream)manual / DNSotomatis dari Docker, Kubernetes
Binary sizekecil, ada di mana-manasatu binary Gosatu binary Go
Cocok untuktim yang butuh kontrol penuhVPS kecil, setup cepatlingkungan container yang berubah cepat

Panduan kasar: nginx kalau kamu butuh kontrol detail dan tim sudah paham sintaksnya. Caddy kalau kamu mau HTTPS jalan lima menit setelah install. Traefik kalau service-mu hidup di Docker dan skala container berubah tiap hari.

#Konsep Inti Reverse Proxy

Reverse proxy duduk di depan backend dan jadi satu-satunya pintu masuk dari internet. Yang bisa dia lakukan:

  • TLS termination: sertifikat cuma dipasang di proxy, backend bicara HTTP polos di jaringan internal
  • Routing: arahkan api.example.com ke service A, path /admin ke service B
  • Load balancing: sebar trafik ke beberapa instance
  • Header manipulation: sisipkan IP klien asli, protokol asli, host asli
  • Buffering dan kompresi: lindungi backend dari klien lambat
plaintext
Internet -> :443 proxy -> app:3000
                        -> api:4000
                        -> admin:5000

Semua contoh di bawah berkaitan erat dengan container. Kalau kamu belum paham docker compose, baca dulu cheat sheet Docker Compose.

#nginx: Routing Dasar

Routing nginx hidup di server block (per domain) dan location block (per path). Urutan pencocokan location:

  1. = exact match, menang kalau ada
  2. ^~ prefix match terpanjang, kalau cocok maka regex dilewati
  3. ~ dan ~* regex (case sensitive dan tidak), dicek berurutan
  4. prefix paling panjang jadi fallback
nginx
server {
    listen 80;
    server_name app.example.com;
 
    # path diteruskan apa adanya ke upstream
    location / {
        proxy_pass http://127.0.0.1:3000;
    }
 
    # perhatikan slash di akhir proxy_pass: /api/users jadi /users
    location /api/ {
        proxy_pass http://127.0.0.1:4000/;
    }
 
    location = /healthz {
        return 200 "ok\n";
        access_log off;
    }
}

Satu slash di akhir proxy_pass mengubah path yang dikirim ke backend. Ini sumber bug klasik yang bikin 404 misterius, jadi hati-hati ya.

#nginx: TLS dengan ACME

nginx tidak punya ACME client bawaan, jadi pakai certbot untuk urusan sertifikat. certbot bisa mode --nginx (baca config langsung) atau webroot.

bash
sudo certbot --nginx -d app.example.com -d www.app.example.com
sudo certbot renew --dry-run

Pembaruan otomatis lewat systemd timer. Setelah renew, nginx perlu reload, tambahkan deploy hook:

bash
sudo certbot renew --deploy-hook "systemctl reload nginx"

Config HTTPS lengkap dengan redirect:

nginx
server {
    listen 80;
    server_name app.example.com;
    return 301 https://$host$request_uri;
}
 
server {
    listen 443 ssl;
    http2 on;
    server_name app.example.com;
 
    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_stapling        on;
 
    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

#nginx: Load Balancing dan Upstream

Definisikan pool backend di block upstream, lalu arahkan proxy_pass ke nama pool itu.

nginx
upstream app {
    least_conn;                              # algoritma: pilih koneksi tersedikit
    server 10.0.0.11:3000 weight=2;          # dapat 2x porsi trafik
    server 10.0.0.12:3000 max_fails=3 fail_timeout=30s;
    server 10.0.0.13:3000 backup;            # cuma dipakai kalau semua utama mati
    keepalive 32;                            # pool koneksi idle per worker
}
 
server {
    listen 443 ssl;
    server_name app.example.com;
    ssl_certificate     /etc/nginx/certs/app.pem;
    ssl_certificate_key /etc/nginx/certs/app.key;
 
    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;              # wajib untuk keepalive upstream
        proxy_set_header Connection "";      # wajib juga, hapus header Connection
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Opsi algoritma yang tersedia:

DirektifPerilaku
default (round robin)bergiliran, dikali weight
least_connserver dengan koneksi aktif paling sedikit
ip_hashIP klien yang sama selalu ke server yang sama (sticky tanpa cookie)
hash $request_urihash berdasarkan URI, cocok untuk cache hit ratio
random two least_connpilih 2 kandidat acak lalu ambil yang paling kosong, murah untuk cluster besar

Catatan penting: keepalive upstream cuma jalan kalau kamu set proxy_http_version 1.1; dan bersihkan header Connection. Tanpa dua baris itu, nginx buka koneksi TCP baru untuk tiap request dan performanya turun drastis.

#Caddy: Reverse Proxy dalam Tiga Baris

Keunggulan Caddy: HTTPS otomatis. Dia minta sertifikat via ACME (Let's Encrypt dan ZeroSSL) saat start, memperbarui sendiri sebelum kedaluwarsa, dan redirect HTTP ke HTTPS tanpa kamu tulis apa pun.

caddyfile
app.example.com {
    encode zstd gzip
    reverse_proxy localhost:3000
}

Untuk domain yang tidak bisa lewat ACME (local dev, internal):

caddyfile
localhost {
    tls internal
    reverse_proxy localhost:3000
}

Routing berdasarkan path pakai handle. handle_path sekalian membuang prefixnya, jadi /api/users tiba di backend sebagai /users.

caddyfile
app.example.com {
    @assets path /assets/*
    handle @assets {
        root * /srv/assets
        file_server
    }
    handle_path /api/* {
        reverse_proxy localhost:4000
    }
    handle {
        reverse_proxy localhost:3000
    }
}

Block paling atas (global) untuk akun email ACME:

caddyfile
{
    email admin@example.com
}

#Caddy: Load Balancing dan Health Check

caddyfile
app.example.com {
    reverse_proxy 10.0.0.11:3000 10.0.0.12:3000 10.0.0.13:3000 {
        lb_policy round_robin
        health_uri      /health
        health_interval 10s
        health_timeout  2s
        fail_duration   30s
        header_up X-Real-IP {remote_host}
    }
}

lb_policy yang sering dipakai: random (default), round_robin, first, least_conn, ip_hash, header, dan cookie (sticky session, cocok kalau session kamu disimpan di memori instance). Health check aktif (health_uri) mendeteksi backend bermasalah dalam hitungan detik, sedangkan fail_duration dan max_fails adalah health check pasif yang mengandalkan kegagalan request nyata.

Defaultnya Caddy tidak percaya header X-Forwarded-For dari siapa pun. Kalau ada proxy lain di depan Caddy (misal CDN), tambahkan:

caddyfile
reverse_proxy localhost:3000 {
    trusted_proxies private_ranges
}

#Traefik: Routing via Label Docker

Traefik memisahkan dua jenis config. Statis (entryPoints, providers, certificatesResolvers) dibaca sekali saat start, biasanya lewat file traefik.yml atau CLI flags. Dinamis (routers, services, middlewares) bisa berubah kapan saja lewat label container atau file di directory provider.

Statis, simpan sebagai traefik.yml:

yaml
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"
 
providers:
  docker:
    exposedByDefault: false
    network: proxy
 
certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web
 
api:
  dashboard: true

Dinamis, cukup label di docker-compose.yml:

yaml
services:
  traefik:
    image: traefik:v3.4
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks: [proxy]
 
  app:
    image: myapp:1.4.2
    networks: [proxy]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`app.example.com`)"
      - "traefik.http.routers.app.entrypoints=websecure"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"
      - "traefik.http.services.app.loadbalancer.server.port=3000"
 
  api:
    image: myapi:2.1.0
    networks: [proxy]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.example.com`) && PathPrefix(`/v1`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=4000"
      - "traefik.http.middlewares.api-strip.stripprefix.prefixes=/v1"
      - "traefik.http.routers.api.middlewares=api-strip@docker"
 
networks:
  proxy:
    name: proxy

Bagian terbaiknya: docker compose up -d --scale api=3 langsung jadi load balancer ke 3 container tanpa config tambahan. Traefik melihat container baru lewat Docker API dan menambahkannya ke pool.

File acme.json harus permission 600 atau Traefik menolak menyimpan sertifikat. Ini error pertama yang hampir semua orang alami kok.

#Traefik: Middleware

Middleware memproses request sebelum sampai ke service. Beberapa yang paling sering dipakai:

yaml
- "traefik.http.middlewares.limit.ratelimit.average=100"
- "traefik.http.middlewares.limit.ratelimit.burst=50"
- "traefik.http.middlewares.secure.headers.stsseconds=31536000"
- "traefik.http.middlewares.secure.headers.contenttypenosniff=true"
- "traefik.http.middlewares.compress.compress=true"
- "traefik.http.services.api.loadbalancer.sticky.cookie=true"
- "traefik.http.services.api.loadbalancer.healthcheck.path=/health"

Urutan middleware di router menentukan urutan eksekusi, jadi taruh rate limit sebelum hal mahal seperti kompresi kalau kamu ingin blokir dulu.

#Header yang Wajib Kamu Pahami

Header berikut adalah kontrak antara proxy dan aplikasi. Backend yang benar membacanya, bukan mengira IP klien adalah IP proxy.

HeaderIsiKegunaan
X-Forwarded-Forrantai IP klien, ditambah tiap hop proxyaudit, rate limit per IP
X-Real-IPIP klien terakhir yang dipercaya proxylog aplikasi
X-Forwarded-Protohttp atau httpsgenerate URL yang benar
X-Forwarded-Hosthost asli yang diminta klienvirtual host di backend
Hostdomain asli dari requestrouting dan CSRF check

Peringatan keamanan: klien bisa mengirim X-Forwarded-For palsu. Proxy yang benar menimpa atau menambah di posisi yang tepat, dan aplikasi hanya boleh percaya hop terakhir sebelum proxy tepercaya. Kalau ada CDN di depan nginx, aktifkan modul realip supaya $remote_addr berisi IP asli:

nginx
# contoh untuk Cloudflare, sesuaikan dengan rentang IP CDN-mu
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
real_ip_header   X-Forwarded-For;
real_ip_recursive on;

WebSocket perlu header upgrade eksplisit di nginx:

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
 
location /ws/ {
    proxy_pass http://app;
    proxy_http_version 1.1;
    proxy_set_header Upgrade    $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 3600s;
}

#Performa dan Tuning

Hal dengan dampak terbesar, urut dari yang paling sering dilupakan:

  1. Keepalive ke upstream. nginx: keepalive 32 plus dua baris wajib di atas. Traefik: atur di serversTransport (forwardingTimeouts.idleConnTimeout). Caddy sudah reuse koneksi secara default.
  2. Kompresi teks. nginx: gzip on; gzip_types text/css application/json;. Caddy: encode zstd gzip. Traefik: middleware compress. Ukuran payload JSON turun 70 persen lebih, gratis.
  3. Buffering. Default nginx buffering respons dulu sebelum kirim ke klien, ini melindungi backend dari klien lambat. Untuk SSE dan streaming (termasuk respons LLM yang panjang), matikan: proxy_buffering off; di nginx dan flush_interval -1 di Caddy.
  4. Timeout yang jujur. proxy_read_timeout default 60 detik di nginx. Untuk endpoint yang lambat, naikkan khusus di location itu, jangan global.
  5. Resource worker. nginx: worker_processes auto; dan worker_connections 4096; di block events. Kalau kamu lihat error "too many open files", naikkan limit file descriptor juga.
  6. HTTP versi baru. http2 on di nginx (versi 1.25.1 ke atas memakai sintaks ini, versi lama pakai listen 443 ssl http2;). Caddy mendukung HTTP/3 dan mengaktifkannya sejak versi 2.6.
  7. Limit ukuran body. client_max_body_size 20m; di nginx supaya upload raksasa tidak menghabiskan memori.

Reload tanpa downtime: nginx -t && nginx -s reload (worker lama menyelesaikan request yang sedang jalan), caddy reload via API admin, dan Traefik hot reload setiap kali dynamic config berubah. Prinsipnya sama: validasi dulu, reload kemudian.

#Debugging Saat Routing Berantakan

bash
nginx -t                                      # uji config sebelum reload
tail -f /var/log/nginx/error.log              # 502 biasanya backend mati atau salah port
caddy validate --config /etc/caddy/Caddyfile
caddy adapt --config Caddyfile --adapter caddyfile   # lihat JSON final hasil adaptasi
docker logs traefik                           # tambahkan --log.level=DEBUG untuk detail router
curl -H "Host: app.example.com" http://127.0.0.1/    # tes routing tanpa perlu DNS
curl -I https://app.example.com                      # cek header respons dan sertifikat

Pola error cepat: 502 Bad Gateway berarti proxy tidak bisa bicara dengan backend (cek port, cek container jalan di network yang sama). 504 Gateway Timeout berarti backend merespons terlalu lambat dibanding timeout. Redirect loop biasanya X-Forwarded-Proto tidak diteruskan dan aplikasi mengira request masih HTTP.

#Checklist Production

  • TLS minimal 1.2, semua trafik 80 diredirect ke 443
  • Health check aktif untuk semua pool load balancing
  • Timeout disetel per endpoint, khusus untuk streaming dan SSE
  • Header X-Forwarded-* diteruskan dan aplikasi membacanya
  • Real IP dikonfigurasi kalau ada CDN di depan proxy
  • Config ada di git, diuji (nginx -t, caddy validate) sebelum reload via CI
  • Rate limit aktif minimal untuk endpoint auth dan API publik
  • Log akses dan error masuk ke agregator (Loki, ELK)
  • Proxy kamu adalah single point of failure: pertimbangkan menjalankannya di setiap node
  • HSTS baru diaktifkan setelah kamu yakin semua subdomain sudah HTTPS

#Glossary

  • Reverse proxy: server yang menerima request klien lalu meneruskannya ke backend di jaringan internal.
  • Upstream: istilah nginx untuk pool backend yang menerima trafik dari proxy.
  • TLS termination: proxy menangani handshake TLS, backend menerima trafik HTTP tanpa enkripsi.
  • ACME: protokol untuk minta dan memperbarui sertifikat secara otomatis, dipakai Let's Encrypt.
  • HTTP challenge: metode ACME yang membuktikan kepemilikan domain lewat file di port 80.
  • SNI: ekstensi TLS yang membawa nama domain saat handshake, dasar dari hosting banyak sertifikat di satu IP.
  • Keepalive: koneksi TCP yang dipakai ulang untuk banyak request, menghemat handshake baru.
  • Sticky session: trafik klien yang sama selalu diarahkan ke instance yang sama, biasanya via cookie atau hash IP.
  • Health check: pemeriksaan berkala untuk menandai backend sehat atau mati, aktif ( probing berkala) atau pasif (berdasarkan kegagalan request).
  • Middleware: unit pemrosesan request di Traefik (strip prefix, rate limit, header) yang dirangkai di router.
  • EntryPoint: titik dengar Traefik, misalnya port 80 (web) atau 443 (websecure).
  • Router: objek Traefik yang mencocokkan request (Host, PathPrefix) lalu mengarahkannya ke service.
  • Buffering: perilaku proxy menampung respons backend sebelum mengirimkannya ke klien lambat.
  • X-Forwarded-For: header rantai yang berisi IP klien ditambah setiap proxy yang dilewati.
  • HSTS: header yang memerintahkan browser hanya mengakses situs via HTTPS selama periode tertentu.
  • Round robin: algoritma load balancing yang membagi request bergiliran ke tiap server.
  • Least connection: algoritma yang mengirim request ke server dengan koneksi aktif paling sedikit.
  • Zero downtime reload: mengganti config tanpa memutus request yang sedang berjalan.

Baca Cheat Sheet Lengkap

Login atau daftar akun gratis untuk membaca cheat sheet ini.

LoginDaftar Gratis
Share: