The Hidden Traps of Nginx: Understanding Directive Context Pitfalls

The Hidden Traps of Nginx: Understanding Directive Context Pitfalls

Salah satu sumber kebingungan terbesar saat bekerja dengan Nginx bukanlah performa atau skalabilitasnya, melainkan aturan konteks directive. Banyak konfigurasi Nginx terlihat valid secara sintaks, tetapi berperilaku tidak sesuai ekspektasi karena directive ditempatkan pada context yang salah.

Memahami directive context adalah kunci untuk:

  • Menghindari konfigurasi yang diam-diam tidak bekerja
  • Mencegah bug produksi yang sulit dideteksi
  • Menulis konfigurasi yang lebih eksplisit dan aman
  • Melakukan debugging dengan cepat

Apa Itu Directive Context?

Dalam Nginx, setiap directive hanya boleh digunakan pada context tertentu. Context merepresentasikan scope eksekusi dari directive tersebut.

Struktur context Nginx bersifat hierarkis:

main
 └── events
 └── http
     └── server
         └── location

Selain itu terdapat context lain seperti:

  • upstream
  • if
  • limit_except
  • stream
  • mail

Directive yang ditempatkan di luar context yang diizinkan akan:

  • Menghasilkan error saat reload, atau
  • Lebih berbahaya: diterima tapi tidak pernah dieksekusi

Pitfall #1: Menganggap Directive Bersifat Global

Contoh Masalah

http {
    proxy_pass http://backend;
}

Konfigurasi di atas valid secara sintaks, tetapi tidak melakukan apa pun.

Penyebab

proxy_pass adalah content directive yang hanya dieksekusi di context:

  • location
  • if (dengan batasan tertentu)

Diletakkan di http tidak akan memicu error, namun tidak pernah dijalankan.

Solusi

server {
    location / {
        proxy_pass http://backend;
    }
}

Pitfall #2: Salah Paham Inheritance (Warisan Konfigurasi)

Tidak semua directive diwariskan ke context bawah.

Contoh

server {
    add_header X-Test "server";

    location /api {
        proxy_pass http://backend;
    }
}

Header X-Test tidak akan muncul pada response /api.

Penyebab

Secara default, add_header tidak diwariskan ke location yang memiliki content handler sendiri.

Solusi

add_header X-Test "server" always;

Atau ulangi di location.


Pitfall #3: Menggunakan if di Dalam location

“If is Evil”

location / {
    if ($request_method = POST) {
        proxy_pass http://backend;
    }
}

Masalah

  • if memiliki context pseudo
  • Tidak semua directive aman di dalam if
  • Dapat menyebabkan internal redirect yang tidak terduga

Kenyataan

if di Nginx bukan flow control biasa, melainkan rewrite-phase instruction.

Solusi Aman

Gunakan:

  • map
  • try_files
  • return
  • Multiple location

Pitfall #4: Regex Location vs Prefix Location

Contoh Konflik

location /api {
    proxy_pass http://backend;
}

location ~ ^/api/v[0-9]+ {
    proxy_pass http://versioned;
}

Request /api/v1 akan masuk ke regex location, meskipun prefix terlihat lebih spesifik.

Aturan Penting

Regex location selalu dievaluasi setelah prefix, kecuali prefix menggunakan ^~.

Solusi

location ^~ /api {
    proxy_pass http://backend;
}

Pitfall #5: root vs alias

Kesalahan Umum

location /static/ {
    root /var/www/static;
}

Request /static/app.js akan dicari di:

/var/www/static/static/app.js

Solusi Benar

location /static/ {
    alias /var/www/static/;
}

Aturan Emas

  • root → menambahkan URI
  • alias → mengganti URI sepenuhnya

Pitfall #6: try_files Mengubah Alur Request

Contoh

location / {
    try_files $uri $uri/ /index.php;
}

Jika file tidak ditemukan:

  • Terjadi internal redirect
  • Request masuk kembali ke phase awal
  • Location matching diulang

Dampak

  • Rewrite dipicu ulang
  • Variabel berubah
  • Bisa memicu loop tak terlihat

Debugging

Aktifkan:

error_log /var/log/nginx/error.log debug;

Pitfall #7: proxy_pass dan Trailing Slash

Contoh Berbahaya

location /api/ {
    proxy_pass http://backend;
}

Request /api/users diteruskan sebagai:

http://backend/api/users

Namun:

location /api/ {
    proxy_pass http://backend/;
}

Request /api/users diteruskan sebagai:

http://backend/users

Dampak

Perbedaan satu karakter (/) dapat mengubah seluruh routing backend.


Pitfall #8: Directive yang Dieksekusi Sekali vs Per Request

Beberapa directive dievaluasi:

  • Saat startup (sekali)
  • Saat reload
  • Per request

Contoh

set $now $time_iso8601;

Nilai $now berubah setiap request, bukan saat reload.

Namun:

env MY_VAR;

Dievaluasi saat startup, bukan per request.


Pitfall #9: Directive Tidak Aktif di Subrequest

Beberapa modul bekerja hanya pada main request, bukan subrequest (misalnya SSI, internal redirect).

Ini sering menyebabkan:

  • Header hilang
  • Rate limit tidak konsisten
  • Cache miss tak terduga

Cara Menghindari Directive Context Pitfall

Checklist Praktis

  • Selalu cek context yang diizinkan pada dokumentasi
  • Gunakan nginx -T untuk dump konfigurasi final
  • Aktifkan debug log saat troubleshooting
  • Minimalkan penggunaan if
  • Gunakan map untuk logic kompleks
  • Pisahkan konfigurasi per domain/service

Kesimpulan

Directive Context Pitfall adalah jebakan klasik Nginx yang sering menimpa engineer berpengalaman sekalipun. Kesalahan kecil dalam penempatan directive dapat menghasilkan perilaku yang salah tanpa error eksplisit.

Dengan memahami:

  • Hierarki context
  • Aturan inheritance
  • Phase eksekusi directive

Anda dapat menulis konfigurasi Nginx yang:

  • Lebih aman
  • Lebih mudah dipahami
  • Lebih mudah di-debug
  • Lebih andal di produksi