Location Block #
Jika Server Block bertugas mendikte mesin atau domain mana yang harus menangani koneksi masuk, maka Location Block bertugas menentukan tindakan spesifik apa yang harus diambil terhadap request tersebut berdasarkan URI path (URL setelah nama domain). Location block adalah tempat di mana sebagian besar logika routing aplikasi kita berada — mulai dari penyajian berkas statis, proteksi direktori admin, penulisan ulang URL, hingga penerusan trafik ke mesin backend (reverse proxying).
Meskipun location block terlihat sederhana, ia memiliki mesin pencocokan (routing engine) yang sangat kompleks dan ketat. Kesalahan kecil dalam penentuan simbol modifier atau urutan penulisan regex dapat menyebabkan file konfigurasi sensitif (seperti berkas .env) bocor ke internet atau skrip PHP dieksekusi sebagai teks biasa. Artikel ini akan membahas modifier pencocokan, membongkar algoritma prioritas pencarian Nginx, menjelaskan implementasi try_files, serta membedah perbedaan krusial antara directive root dan alias.
Lima Modifier Pencocokan: Sintaks & Cara Kerja #
Di dalam Nginx, modifier adalah simbol khusus yang diletakkan tepat setelah kata kunci location dan sebelum string path pencarian. Simbol ini menentukan perilaku perbandingan string yang dilakukan oleh Nginx:
location modifier /path/target/ {
# directive ...
}
Berikut adalah penjelasan mendalam mengenai kelima tipe modifier yang didukung oleh Nginx:
1. Tanpa Modifier (Prefix Match Biasa) #
Jika kita menulis location tanpa simbol apapun, Nginx melakukan pencocokan awalan (prefix match).
- Perilaku: URL request yang dimulai dengan string target akan cocok.
- Contoh:
location /images/ { ... }- ✓ Cocok untuk:
/images/,/images/logo.png,/images/temp/photo.jpg. - ✗ Tidak cocok untuk:
/my-images/,/images(tanpa trailing slash).
- ✓ Cocok untuk:
2. = (Exact Match / Pencocokan Tepat)
#
Modifier sama dengan = memerintahkan Nginx untuk membandingkan URI request secara tepat karakter-demi-karakter dengan target.
- Perilaku: Hanya cocok jika URI request sama persis dengan string target. Begitu cocok, Nginx langsung menghentikan seluruh pencarian routing lainnya.
- Contoh:
location = / { ... }- ✓ Cocok untuk:
/saja. - ✗ Tidak cocok untuk:
/index.html,/about. - Best Practice: Gunakan modifier ini untuk meningkatkan kecepatan pemrosesan URL yang paling sering diakses (seperti beranda
/atau file/favicon.ico) demi menghindari traversal pencarian memori.
- ✓ Cocok untuk:
3. ^~ (Prefix Match Prioritas Tinggi)
#
Modifier ^~ bekerja seperti prefix match biasa (mencocokkan awalan), tetapi memiliki sifat protektif khusus.
- Perilaku: Jika request cocok dengan prefix ini, dan prefix ini terbukti sebagai prefix terpanjang yang cocok di sistem, Nginx akan langsung menggunakan blok ini dan mengabaikan semua pencarian regex (
~atau~*). - Contoh:
location ^~ /static/ { ... }- Mengapa ini penting? Bayangkan kita memiliki folder
/static/berisi aset CSS dan gambar, dan kita juga memiliki handler regex PHPlocation ~ \.php$. Jika pengguna meminta file/static/avatar.php(mungkin disuntikkan peretas), Nginx tanpa^~akan memilih handler PHP karena regex memiliki prioritas lebih tinggi dibanding prefix. Dengan^~, Nginx langsung menyajikan file statis tersebut tanpa mengeksekusinya sebagai PHP, mencegah serangan eksekusi kode.
- Mengapa ini penting? Bayangkan kita memiliki folder
4. ~ (Case-Sensitive Regular Expression)
#
Menggunakan pencocokan ekspresi reguler (Regex) peka huruf besar-kecil.
- Perilaku: Menggunakan mesin regex PCRE untuk mengevaluasi URL.
- Contoh:
location ~ \.php$ { ... }- ✓ Cocok untuk:
/index.php,/user/profile.php. - ✗ Tidak cocok untuk:
/index.PHP(huruf besar).
- ✓ Cocok untuk:
5. ~* (Case-Insensitive Regular Expression)
#
Menggunakan pencocokan regex tidak peka huruf besar-kecil.
- Perilaku: Sama seperti
~, tetapi mengabaikan perbedaan kapitalisasi karakter. - Contoh:
location ~* \.(jpg|jpeg|png|gif|ico)$ { ... }- ✓ Cocok untuk:
/logo.png,/banner.JPG,/avatar.Png.
- ✓ Cocok untuk:
Algoritma Prioritas Pencocokan (Routing Priority) #
Ketika ada sebuah request masuk, Nginx mungkin menemukan beberapa location block yang berpotensi cocok dengan URI tersebut. Nginx menggunakan algoritma prioritas internal untuk menjamin hasil pencocokan bersifat deterministik (selalu menghasilkan keputusan yang sama).
Berikut adalah alur keputusan sistematis yang dilewati Nginx untuk memilih location block:
flowchart TD
Start["Request URI Tiba (misal: /assets/app.js)"] --> Step1{"1. Apakah ada Match Exact (=) <br> yang cocok dengan URI?"}
Step1 -->|"Ya"| ReturnExact["Gunakan Blok Exact (=) <br> (Proses Selesai)"]
Step1 -->|"Tidak"| Step2["2. Cari semua Prefix Match biasa <br> (tanpa modifier & ^~). <br> Catat prefix tercocok terpanjang."]
Step2 --> Step3{"3. Apakah prefix terpanjang <br> tercata memiliki modifier ^~?"}
Step3 -->|"Ya"| ReturnPriority["Gunakan Blok Prefix Prioritas (^~) <br> (Abaikan Regex - Selesai)"]
Step3 -->|"Tidak"| Step4{"4. Cari kecocokan Regex (~ dan ~*) <br> sesuai urutan penulisan di file config."}
Step4 -->|"Ditemukan Regex Cocok"| ReturnRegex["Gunakan Blok Regex Pertama yang cocok <br> (Selesai)"]
Step4 -->|"Tidak Ada Regex Cocok"| ReturnFallback["5. Gunakan fallback Prefix Match <br> terpanjang yang dicatat pada langkah 2"]
style Start stroke:#0288d1,stroke-width:2.5px
style Step3 stroke:#f57c00,stroke-width:2px
style ReturnExact stroke:#388e3c,stroke-width:1.5px
style ReturnPriority stroke:#d32f2f,stroke-width:2pxContoh Simulasi Kasus Nyata #
Mari kita uji algoritma di atas menggunakan konfigurasi server block berikut:
server {
location / {
# Blok A (Fallback)
}
location = /favicon.ico {
# Blok B (Exact Match)
}
location ^~ /static/ {
# Blok C (Prefix Prioritas)
}
location ~* \.(js|css)$ {
# Blok D (Regex File Aset)
}
location ~ \.php$ {
# Blok E (Regex PHP)
}
}
Mari kita simulasi beberapa request URI yang masuk ke server:
- Request
GET /favicon.ico- Hasil: Blok B dipilih. Alasan: Blok B menggunakan modifier exact match (
=), langsung terpilih di Langkah 1.
- Hasil: Blok B dipilih. Alasan: Blok B menggunakan modifier exact match (
- Request
GET /static/js/app.js- Hasil: Blok C dipilih. Alasan: Blok C cocok dengan prefix
/static/terpanjang. Karena menggunakan^~, Nginx langsung berhenti dan tidak mengevaluasi Blok D (Regex JS), meskipun file berakhiran.js.
- Hasil: Blok C dipilih. Alasan: Blok C cocok dengan prefix
- Request
GET /assets/style.css- Hasil: Blok D dipilih. Alasan: Prefix terpanjang yang cocok adalah
/(Blok A), yang tidak menggunakan^~. Nginx lanjut mengevaluasi regex dan menemukan Blok D cocok dengan akhiran.css.
- Hasil: Blok D dipilih. Alasan: Prefix terpanjang yang cocok adalah
- Request
GET /index.php- Hasil: Blok E dipilih. Alasan: Nginx melewati exact dan prefix prioritas, lalu mencocokkan regex dan menemukan Blok E cocok dengan akhiran
.php.
- Hasil: Blok E dipilih. Alasan: Nginx melewati exact dan prefix prioritas, lalu mencocokkan regex dan menemukan Blok E cocok dengan akhiran
- Request
GET /about-us- Hasil: Blok A dipilih. Alasan: Tidak ada exact, prefix prioritas, atau regex yang cocok. Nginx menggunakan fallback prefix tercocok terpanjang, yaitu
/.
- Hasil: Blok A dipilih. Alasan: Tidak ada exact, prefix prioritas, atau regex yang cocok. Nginx menggunakan fallback prefix tercocok terpanjang, yaitu
Named Locations (Lokasi Bernama @)
#
Nginx mendukung pembuatan Named Locations yang ditandai dengan awalan karakter @. Blok lokasi bernama ini tidak digunakan untuk melayani request HTTP luar secara langsung, melainkan bertindak sebagai sub-fungsi internal yang dipanggil oleh directive lain seperti try_files atau error_page.
server {
listen 80;
server_name example.com;
location / {
# Coba serve file statis di disk.
# Jika file tidak ada, lemparkan request ke named location @api_backend.
try_files $uri $uri/ @api_backend;
}
location @api_backend {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
# ...
}
}
- Keunggulan: Menggunakan named location lebih cepat dan hemat memori dibandingkan melakukan pengalihan internal biasa (internal redirect menggunakan path seperti
/fallback/), karena Nginx tidak perlu mengulang siklus pencarian location block dari awal.
Implementasi try_files untuk SPA dan PHP MVC #
Directive try_files adalah perkakas penting di dalam location block yang menginstruksikan Nginx untuk mencari berkas fisik di disk secara berurutan, dan menggunakan berkas pertama yang ditemukan.
Sintaks penulisan try_files:
try_files file1 [file2 ...] fallback_uri_atau_named_location;
Berikut adalah dua implementasi try_files yang wajib dikuasai untuk arsitektur aplikasi modern:
1. Pola Router Single Page Application (React / Vue / Angular) #
Pada aplikasi SPA, peramban klien memproses seluruh routing halaman di sisi klien menggunakan JavaScript (client-side routing). Jika pengguna me-refresh halaman pada path example.com/dashboard/users, Nginx secara fisik tidak memiliki file tersebut di disk.
server {
listen 80;
server_name example.com;
root /var/www/my-spa/dist;
location / {
# 1. Coba cari berkas asli (misal: /assets/app.js)
# 2. Coba cari direktori (misal: /assets/)
# 3. Jika tidak ada, selalu kembalikan index.html
try_files $uri $uri/ /index.html;
}
}
Dengan konfigurasi di atas, Nginx akan menyajikan berkas index.html utama untuk semua URL tidak dikenal, membiarkan aplikasi JavaScript dimuat oleh browser dan menangani routing internal halaman secara mandiri.
2. Pola Front Controller PHP (Laravel / WordPress) #
Framework PHP modern menyalurkan seluruh request masuk melalui satu file gerbang masuk utama, yaitu index.php.
server {
listen 80;
server_name example.com;
root /var/www/my-laravel/public;
index index.php;
location / {
# Jika file/folder tidak ada, alihkan request ke index.php
# dengan melampirkan parameter query string asli ($query_string)
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Perbedaan Krusial: root vs alias #
Salah satu kesalahan paling sering yang ditemui pada konfigurasi Nginx adalah tertukarnya penggunaan directive root dan alias di dalam location block. Kesalahan ini berujung pada error 404 Not Found karena Nginx mencari file di lokasi disk yang salah.
1. Directive root (Penggabungan Path)
#
Directive root menetapkan direktori dasar untuk pencarian file. Nginx akan menggabungkan isi path root dengan seluruh string URI request.
location /static/ {
root /var/www/assets;
}
- Alur Resolusi: Jika ada request untuk
/static/css/style.css, Nginx akan menggabungkan keduanya menjadi: $$\text{Path Hasil} = \text{root} + \text{URI} = \text{/var/www/assets} + \text{/static/css/style.css}$$ $$\text{Path Hasil} = \text{/var/www/assets/static/css/style.css}$$ - Perhatikan: Sub-folder
/static/wajib ada di dalam/var/www/assets/.
2. Directive alias (Penggantian Path)
#
Directive alias melakukan pemetaan ulang direktori secara penuh. Nginx akan mengganti bagian prefix location dengan path alias.
location /static/ {
alias /var/www/assets/;
}
- Alur Resolusi: Jika ada request untuk
/static/css/style.css, Nginx akan membuang part/static/dari URI dan menggantinya dengan path alias: $$\text{Path Hasil} = \text{alias} + (\text{URI} - \text{prefix}) = \text{/var/www/assets/} + \text{css/style.css}$$ $$\text{Path Hasil} = \text{/var/www/assets/css/style.css}$$ - Perhatikan: Sub-folder
/static/tidak perlu ada di dalam direktori target/var/www/assets/.
Matriks Perbandingan Ringkas: #
| Dimensi Perbandingan | Directive root | Directive alias |
|---|---|---|
| Metode Pencarian | Menggabungkan path dengan seluruh URI. | Mengganti string prefix dengan path alias. |
Trailing Slash / | Tidak sensitif terhadap slash penutup. | Sangat Sensitif. Slash pada location dan alias wajib selaras. |
| Kompatibilitas | Dapat digunakan di seluruh context. | Hanya valid digunakan di dalam location block. |
| Regex Support | Mendukung regex dengan aman. | Membutuhkan capture groups regex manual agar berfungsi. |
Bahaya Off-by-One Slash pada alias! Jika kita menggunakan
alias, pastikan keberadaan tanda garis miring (slash/) di akhir stringlocationdanaliassaling cocok secara konsisten:# ANTI-PATTERN: Menyebabkan kegagalan pencarian file karena kelebihan atau kekurangan slash location /static/ { alias /var/www/assets; # Kekurangan slash di akhir! }Jika kita meminta file
/static/app.jspada konfigurasi salah di atas, Nginx akan menerjemahkannya ke/var/www/assetsapp.js(tanpa pembatas direktori), yang mengakibatkan error404 Not Found. Selalu samakan keberadaan trailing slash: jika location memilikinya, alias wajib memilikinya.
Penggunaan alias di dalam Regular Expression Location Block #
Hal krusial yang perlu kita ketahui adalah, secara default Nginx tidak mendukung penggunaan alias biasa di dalam location block berbasis regex. Jika kita menulis:
# ANTI-PATTERN: Nginx tidak tahu cara memetakan path dinamis ke disk
location ~* ^/images/(.+\.(png|jpg))$ {
alias /var/www/data/media/;
}
Aturan di atas akan memicu error karena Nginx tidak dapat menghitung bagian URI mana yang harus dibuang dan diganti.
Solusi yang Benar (Menggunakan Capture Groups): #
Jika kita terpaksa menggunakan alias di dalam regex location, kita wajib menangkap segmen path yang diinginkan menggunakan tanda kurung regex (capture groups) dan menyatakannya secara eksplisit menggunakan variabel $1, $2, dst. pada direktori alias:
# BENAR: Menangkap nama file ke dalam variabel $1
location ~* ^/images/(.+\.(png|jpg))$ {
alias /var/www/data/media/$1;
}
Pada contoh ini, jika ada request /images/user-profile/avatar.png, Nginx menangkap string user-profile/avatar.png ke dalam variabel $1 dan memetakan pencarian file ke /var/www/data/media/user-profile/avatar.png secara akurat.
Nested Location: Penggunaan Aman & Batasan #
Nginx mengizinkan pembuatan location block yang berada di dalam location block lainnya (nesting). Penggunaan location bersarang ini berguna untuk mengisolasi penanganan khusus untuk sub-direktori tertentu.
Berikut adalah pola konfigurasi nested location tingkat produksi:
server {
listen 80;
server_name example.com;
root /var/www/html;
# Outer Location: Menangani area portal admin
location /admin/ {
# Batasi akses hanya untuk IP internal tim IT
allow 192.168.1.0/24;
deny all;
# Inner (Nested) Location: Menangani file PHP khusus admin
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
- Mengapa ini aman? Nested location mewarisi batasan keamanan (
allow/deny) dari blok luarnya secara otomatis. File PHP di dalam/admin/hanya dapat diakses oleh IP yang diizinkan, sementara file PHP di luar/admin/tetap dapat diakses oleh publik (jika ada handler PHP luar). - Warning: Batasi kedalaman bersarang hingga maksimal 2 tingkat saja. Struktur nested location yang terlalu dalam memicu overhead pembacaan memori yang rumit dan meningkatkan risiko miskonfigurasi pewarisan.
Anti-Patterns: Jebakan Bayangan Regex (Regex Shadow Trap) #
Saat menulis banyak location block menggunakan regular expressions (~ atau ~*), kita harus mengingat bahwa Nginx mengevaluasi regex berdasarkan urutan kemunculannya di dalam berkas konfigurasi.
# ANTI-PATTERN: Blok kedua tidak akan pernah dieksekusi!
server {
# 1. Menangkap semua file berekstensi .php
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# 2. Blok proteksi khusus untuk area admin
location ~ /admin\.php$ {
allow 192.168.1.100; # Hanya boleh diakses IP tim internal
deny all;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
Mengapa Ini Terjadi? #
Jika pengguna mengakses /admin.php, Nginx memindai konfigurasi dari atas ke bawah. Nginx menemukan Blok 1 (~ \.php$) cocok dengan URI tersebut, langsung mengeksekusinya, dan berhenti mencari. Blok 2 yang memuat aturan firewall pengaman IP tidak pernah dievaluasi. Akibatnya, halaman admin bocor ke internet luar.
Solusi yang Benar: #
Tulis lokasi regex yang paling spesifik (paling ketat penulisan jalurnya) lebih tinggi daripada regex global yang umum:
# BENAR: Urutkan dari yang paling spesifik ke yang paling umum
server {
# 1. Taruh proteksi spesifik paling atas
location ~ /admin\.php$ {
allow 192.168.1.100;
deny all;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# 2. Fallback untuk file PHP biasa
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
Ringkasan #
- Modifier location mengendalikan logika routing:
=untuk exact, tanpa modifier untuk prefix,^~untuk prefix prioritas (skip regex), dan~/~*untuk regex.- Algoritma prioritas Nginx mendahulukan exact match
=, dilanjutkan prefix tercocok terpanjang (jika memiliki^~langsung berhenti), lalu memindai regex sesuai urutan file, baru terakhir fallback ke prefix terpanjang biasa.- Directive
try_fileswajib digunakan untuk mendukung routing dinamis pada aplikasi SPA (React/Vue) dan Front Controller MVC (Laravel/WordPress).- Named location (
@name) bertindak sebagai sub-fungsi internal cepat untuk pengalihan trafik internal tanpa memicu siklus pemindaian ulang.rootmenggabungkan seluruh URI request dengan path root, sedangkanaliasmenggantikan prefix location dengan path alias.- Penggunaan
aliasdi dalam regex wajib menyertakan tangkapan variabel (seperti$1) guna mengarahkan path berkas disk secara dinamis.- Urutan penulisan regex sangat penting; letakkan blok regex yang lebih spesifik di atas regex yang bersifat umum untuk menghindari penimpaan aturan (regex shadow).