Nginx Basics — DevOps

Apa itu Nginx? Nginx (dibaca "engine-x") adalah web server yang juga bisa berfungsi sebagai reverse proxy, load balancer, dan HTTP cache. Dikenal sangat cepat…

Nginx (dibaca "engine-x") adalah web server: program yang menunggu request HTTP di port 80 (dan 443 untuk HTTPS), lalu menjawabnya, entah dengan file dari disk, entah dengan meneruskannya ke app di belakangnya. Bayangin resepsionis gedung perkantoran. Gedungnya satu alamat, tapi kantornya banyak. Tamu datang, resepsionis melihat nama kantor yang dicari (di nginx: header Host), lalu ruangan yang dituju (di nginx: path URL), dan mengantarnya ke tempat yang benar.

🧪 Tebakan cepat: config catatan.example.com punya location /lampiran/ (folder lampiran user) dan location ~* \.(jpg|jpeg|png|svg|css|js)$ (cache 30 hari untuk gambar dan aset). Request GET /lampiran/a4c2e9f1.jpg ditangani location yang mana? Tebak dulu, jawabannya ada di bagian "Urutan nginx memilih location".

Memasang nginx di web-1

Di web-1 (Ubuntu 24.04), sudo apt install nginx memasangnya, dan systemd langsung menjalankannya. curl -I http://localhost (header saja) menjawab HTTP/1.1 200 OK dengan Server: nginx/1.24.0 (Ubuntu): itu halaman bawaan "Welcome to nginx!".

Server block: satu situs, satu blok

Situs catatan-api di catatan.example.com punya file statis: halaman depan index.html dan asetnya di /var/www/catatan, plus lampiran yang di-upload user. App Express-nya baru disambungkan di pelajaran berikutnya (reverse proxy); sekarang nginx melayani file statisnya dulu. Config-nya ditulis di /etc/nginx/sites-available/catatan:

server {
    listen 80;
    listen [::]:80;
    server_name catatan.example.com www.catatan.example.com;
    root /var/www/catatan;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Nyalakan situsnya dengan sudo ln -s /etc/nginx/sites-available/catatan /etc/nginx/sites-enabled/, matikan halaman bawaan dengan sudo rm /etc/nginx/sites-enabled/default, lalu uji dan terapkan (bagian terakhir).

Di latihan, kamu menyusun teks server block dari object { port, serverName, root, locations }. Baris di dalam server diindentasi 4 spasi, isi location 8 spasi, dan tiap directive diakhiri ;. Untuk { port: 80, serverName: "myapp.com", root: "/var/www/html", locations: [{ path: "/", directive: "try_files $uri /index.html" }] } hasilnya persis:

server {
    listen 80;
    server_name myapp.com;
    root /var/www/html;
    location / {
        try_files $uri /index.html;
    }
}

Nginx memilih server block dari port dan Host

Browser yang membuka http://catatan.example.com tersambung ke IP web-1, 203.0.113.10, port 80, lalu mengirim Host: catatan.example.com. Nginx mengambil semua server block yang listen di port itu dan mencocokkan Host dengan server_name mereka. Kalau gak ada yang cocok, dia memakai default server port itu: yang ditandai default_server, atau server block pertama kalau gak ada yang ditandai.

Di bawah server block catatan, web-1 punya satu blok penampung:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}
Request Host Server block Hasil
curl -I http://catatan.example.com/ catatan.example.com catatan 200 OK
curl -I http://www.catatan.example.com/ www.catatan.example.com catatan 200 OK
curl -I http://203.0.113.10/ 203.0.113.10 default koneksi diputus

server_name _ cuma nama yang gak mungkin cocok. return 444 kode khusus nginx: tutup koneksi tanpa jawaban sama sekali, jadi curl menulis curl: (52) Empty reply from server. Bot yang memindai IP acak gak dapat apa-apa.

Urutan nginx memilih location

Server block catatan yang lengkap, sama dengan yang ada di Lab:

    location = /favicon.ico { access_log off; log_not_found off; }

    location /lampiran/ {
        alias /srv/catatan-api/storage/lampiran/;
    }

    location ~* \.(jpg|jpeg|png|svg|css|js)$ { expires 30d; }

    location / {
        try_files $uri $uri/ =404;
    }

Nginx memilih location dengan empat langkah. Urutan location prefix di file gak berpengaruh, tapi urutan regex berpengaruh:

  1. Ada = yang cocok persis? Pakai itu, selesai.
  2. Cari prefix terpanjang yang cocok. Kalau prefix itu ditandai ^~, pakai itu, selesai.
  3. Cek regex berurutan sesuai tulisan di file. Regex pertama yang cocok menang.
  4. Gak ada regex yang cocok? Pakai prefix terpanjang dari langkah 2.
Path Location terpilih Hasil
/favicon.ico = /favicon.ico (langkah 1) 200, favicon
/ / (langkah 4) 200, index.html
/catatan/12 / (langkah 4) 404, API-nya belum disambungkan
/assets/app.3f9a1c.js regex (langkah 3) 200, cache 30 hari
/lampiran/a4c2e9f1.jpg regex (langkah 3) 404 Not Found

Lihat baris terakhir. Di langkah 2, prefix terpanjangnya /lampiran/, tapi dia prefix biasa, jadi nginx lanjut ke langkah 3, dan .jpg cocok dengan regex. Regex menang, lalu nginx mencari /var/www/catatan/lampiran/a4c2e9f1.jpg, yang gak ada: 404. Itu jawaban tebakannya. Perbaikannya satu tanda: location ^~ /lampiran/. Sekarang langkah 2 berhenti di /lampiran/, dan regex gak pernah dicek.

Cek dulu dengan nginx -t, baru reload

Tiap kali config diubah, uji dulu, baru terapkan:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx

Kalau titik koma setelah root /var/www/catatan (baris 5) hilang, nginx membaca terus sampai titik koma berikutnya, jadi dia melihat root /var/www/catatan index index.html;, satu directive dengan tiga argumen:

$ sudo nginx -t
nginx: [emerg] invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/catatan:6
nginx: configuration file /etc/nginx/nginx.conf test failed

⚠️ Jebakan yang sering ketemu

TL;DR: Nginx adalah web server (dan reverse proxy, pelajaran berikutnya) yang menjawab request di port 80 dan 443. Config tiap situs ditulis di sites-available, dinyalakan lewat symlink di sites-enabled. Server block (server { listen; server_name; root; location }) dipilih dari port dan header Host; yang gak cocok jatuh ke default_server. Location dipilih dengan urutan: = persis, lalu prefix terpanjang (berhenti kalau ^~), lalu regex ~/~* sesuai urutan di file, lalu prefix terpanjang tadi. Tiap directive diakhiri ;. Selalu sudo nginx -t dulu, lalu sudo systemctl reload nginx (atau nginx -s reload), yang gak memutus koneksi dan menolak config rusak.

Yang akan kamu pelajari