Location Block

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).

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.

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 PHP location ~ \.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.

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).

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.

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:2px

Contoh 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:

  1. Request GET /favicon.ico
    • Hasil: Blok B dipilih. Alasan: Blok B menggunakan modifier exact match (=), langsung terpilih di Langkah 1.
  2. 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.
  3. 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.
  4. 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.
  5. 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 /.

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 PerbandinganDirective rootDirective alias
Metode PencarianMenggabungkan 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.
KompatibilitasDapat digunakan di seluruh context.Hanya valid digunakan di dalam location block.
Regex SupportMendukung 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 string location dan alias saling 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.js pada konfigurasi salah di atas, Nginx akan menerjemahkannya ke /var/www/assetsapp.js (tanpa pembatas direktori), yang mengakibatkan error 404 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_files wajib 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.
  • root menggabungkan seluruh URI request dengan path root, sedangkan alias menggantikan prefix location dengan path alias.
  • Penggunaan alias di 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).

← Sebelumnya: Server Block   Berikutnya: Variabel Bawaan →

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