Chapter DNS Server memberi nama pada alamat server kita; sekarang kita atur siapa yang menjawab ketika nama itu dipanggil. Reverse proxy adalah lapisan yang berdiri paling depan: satu pintu yang menerima seluruh permintaan dari klien, lalu meneruskannya ke aplikasi di belakangnya. Dengan pola ini, satu alamat publik bisa melayani banyak aplikasi, membagi beban ke beberapa instance, dan menangani TLS di satu tempat. Mesin latihan kita tidak memasang Nginx, jadi file konfigurasi kita bedah lewat fixture, sementara logika pembagian beban kita uji sungguhan dengan dua server lokal di loopback.

Forward Proxy versus Reverse Proxy #

Kata proxy berarti perantara, dan arah perantara itulah yang membedakan keduanya. Forward proxy berdiri di sisi klien: browser kantor yang meneruskan permintaan ke internet lewat proxy, sehingga server tujuan hanya melihat alamat proxy, bukan alamat klien. Reverse proxy kebalikannya — berdiri di sisi server, menyambut klien yang datang lalu menghubungi backend atas nama klien. Perbandingan keduanya:

AspekForward proxyReverse proxy
Mewakiliklienserver / backend
Dipasang olehpihak klien (kantor, ISP)admin server
Terlihat oleh klienya, eksplisit dikonfigurasitidak — terasa seperti server biasa
Contoh klasikproxy sekolah, cache ISPpintu depan situs besar

Di mata klien, reverse proxy memang tak terlihat: curl ke alamat situs terasa seperti menyapa satu server, padahal jawaban bisa datang dari salah satu dari sepuluh mesin di belakangnya.

Empat Pekerjaan yang Diembankan pada Reverse Proxy #

Pola satu pintu depan ini dipakai untuk empat pekerjaan yang berulang di dunia server. Pertama, TLS termination: sertifikat dan negosiasi enkripsi cukup dikelola di satu tempat, sementara backend berbicara polos di jaringan internal — pengelolaan sertifikatnya sendiri kita bahas tuntas di Chapter TLS dan SSL Certificates . Kedua, load balancing: permintaan dibagi ke beberapa instance aplikasi agar tidak ada satu mesin yang kewalahan. Ketiga, caching dan kompresi: jawaban yang sering diminta bisa disimpan di depan, dan respons dikompresi sekali untuk semua klien. Keempat, melindungi backend: aplikasi cukup mendengarkan di 127.0.0.1, tidak pernah tersentuh internet secara langsung, sehingga permukaan serangan menyempit dan backend bisa direstart tanpa klien sadar.

proxy_pass: Meneruskan Permintaan ke Backend #

Di Nginx — yang server block dan direktori konfigurasinya sudah kita kenal dari Chapter nginx — seluruh pekerjaan reverse proxy berpusat pada satu directive: proxy_pass. Fixture reverse-proxy.conf di bundle chapter ini memperlihatkan konfigurasi lengkapnya:

bash
cat reverse-proxy.conf

Output yang Dihasilkan:

text
upstream backend.example.com {
    server 127.0.0.1:8231;
    server 127.0.0.1:8232;
}

server {
    listen 80;
    server_name app.latihan.example.com;

    location / {
        proxy_pass http://backend.example.com/;
        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;
    }
}

Mari kita bedah blok demi blok:

  1. Blok upstream backend.example.com: mendefinisikan kelompok backend — dua instance yang masing-masing mendengarkan di 127.0.0.1 port 8231 dan 8232. Nama upstream hanyalah label pilihan kita, dan menjadi satu-satunya tempat yang perlu disentuh saat daftar backend berubah.
  2. server { listen 80; server_name app.latihan.example.com; }: pintu depan yang menghadap klien — pasangan listen dan server_name sudah kita bedah di Chapter Web Server .
  3. location / { ... }: semua path jatuh ke blok ini, sehingga seluruh permintaan diteruskan tanpa kecuali.
  4. proxy_pass http://backend.example.com/;: inti reverse proxy — Nginx membuka koneksi ke salah satu anggota upstream, mengirim permintaan, lalu mengalirkan jawabannya kembali ke klien. Tanda / di akhir membuat directive ini membawa URI: bagian permintaan yang cocok dengan location diganti oleh URI tersebut. Pada location / hasilnya sama persis dengan tanpa garis miring; bentuk ber-URI baru berdampak pada location yang lebih spesifik, misalnya location /api/ yang ingin memangkas awalan /api sebelum meneruskan.
  5. proxy_set_header Host $host;: nama domain asli tetap dikirim ke backend, agar aplikasi yang melayani banyak domain tetap tahu domain mana yang diminta.
  6. proxy_set_header X-Real-IP $remote_addr;: alamat IP klien asli — tanpa baris ini, semua permintaan yang dilihat backend datang dari 127.0.0.1.
  7. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;: rantai alamat klien; nilai $proxy_add_x_forwarded_for menambahkan alamat klien ke daftar yang sudah ada, sehingga tiap proxy yang dilalui meninggalkan jejak.
  8. proxy_set_header X-Forwarded-Proto $scheme;: memberi tahu backend skema asli permintaan, http atau https — penting ketika backend menyusun URL absolut.

Load Balancing: Membagi Beban ke Banyak Backend #

Saat upstream berisi lebih dari satu server, Nginx otomatis membagi permintaan dengan round robin: bergiliran rata, backend pertama lalu kedua, kembali ke pertama, begitu seterusnya. Dua metode lain dinyalakan dengan satu baris di dalam blok upstream:

MetodeBaris di blok upstreamCara memilih backend
Round robintanpa baris (bawaan)bergiliran rata ke semua anggota
Least connectionsleast_conn;anggota dengan koneksi aktif paling sedikit
IP haship_hash;alamat IP klien yang sama selalu menuju anggota yang sama

Kita buktikan giliran round robin dengan dua backend sungguhan di loopback — dua instance python3 -m http.server dengan isi berbeda:

bash
mkdir -p backend-1 backend-2
printf 'jawaban dari aplikasi-1\n' > backend-1/index.html
printf 'jawaban dari aplikasi-2\n' > backend-2/index.html
python3 -m http.server 8231 --bind 127.0.0.1 --directory backend-1 >/dev/null 2>&1 &
pid1=$!
python3 -m http.server 8232 --bind 127.0.0.1 --directory backend-2 >/dev/null 2>&1 &
pid2=$!
for i in 1 2 3 4 5; do
  curl -s -o /dev/null 127.0.0.1:8231/ && curl -s -o /dev/null 127.0.0.1:8232/ && break
  sleep 0.2
done
ss -tln | grep 8231
ss -tln | grep 8232
gilir=("127.0.0.1:8231/" "127.0.0.1:8232/")
for i in 0 1 2 3 4 5; do
  curl -s "${gilir[$(( i % 2 ))]}"
done
kill "$pid1" "$pid2"

Output yang Dihasilkan:

text
LISTEN 0      5          127.0.0.1:8231       0.0.0.0:*   
LISTEN 0      5          127.0.0.1:8232       0.0.0.0:*   
jawaban dari aplikasi-1
jawaban dari aplikasi-2
jawaban dari aplikasi-1
jawaban dari aplikasi-2
jawaban dari aplikasi-1
jawaban dari aplikasi-2

Enam baris jawaban berselang-seling itulah round robin yang dikerjakan proxy_pass pada upstream dua anggota. Mari kita bedah bagiannya:

  1. Baris 1-3: menyiapkan dua backend dengan isi berbeda — isi inilah identitas tiap instance saat kita membaca jawaban.
  2. Baris 4-7: menyalakan kedua backend sebagai background process di port berbeda; keduanya diikat ke 127.0.0.1 saja, persis posisi backend di balik reverse proxy.
  3. Baris 9-11: ss -tln memastikan keduanya benar-benar mendengarkan — pola pemeriksaan dari Chapter ss dan netstat .
  4. Baris 12 (gilir=(...)): array dua alamat — versi shell dari blok upstream; curl menerima alamat tanpa skema dan menganggapnya http.
  5. Baris 14 (${gilir[$(( i % 2 ))]}): jantung round robin — operator modulo % memetakan nomor permintaan ke indeks array menjadi 0, 1, 0, 1, sehingga beban terbagi rata. Nginx memakai penghitung internal yang sama untuk memilih anggota upstream berikutnya.
  6. Baris 16 (kill ...): membereskan kedua backend setelah latihan.

Selagi giliran berjalan, Nginx juga mengawasi kesehatan anggota upstream secara pasif: setiap percobaan koneksi yang gagal dihitung. Baris berikut memberi ruang tiga kegagalan dalam 30 detik sebelum anggota dianggap tidak tersedia selama 30 detik:

ini
server 127.0.0.1:8233 max_fails=3 fail_timeout=30s;

Anggota yang sedang ditandai mati tidak menerima permintaan baru sampai masa cobaannya habis — permintaan klien tetap dilayani anggota lain tanpa satu pun error yang bocor ke luar. Dua pengaturan lanjutan yang sering menyertai tabel ini: buffering menyala bawaannya, sehingga jawaban backend ditampung dulu di memori proxy sebelum dituliskan pelan-pelan ke klien yang lambat, dan timeout — proxy_read_timeout 60s bawaannya — memutus tunggu ketika backend terlalu lama diam.

Pintu depan ini baru separuh cerita: begitu klien mengharapkan gembok HTTPS di browser, reverse proxy-lah pihak yang paling sering memegang sertifikat. Cara membuat, meminta, dan memperbaruinya adalah materi Chapter TLS dan SSL Certificates .

Referensi lanjut: dokumentasi modul proxy Nginx untuk seluruh directive proxy_*, serta dokumentasi modul upstream untuk pembagian beban dan health check.