Linux : Nginx Dasar dan Virtual Host

Revision as of 07:03, 8 November 2026 by Maintenance script (talk | contribs) (Artikel baru: Nginx dasar dan virtual host (konsep tiga lapis pemilihan situs))
(diff) ← Older revision | Latest revision (diff) | Newer revision β†’ (diff)

🎯 Tujuan

Setelah membaca artikel ini, kamu bisa menjelaskan bagaimana Nginx memilih situs yang menjawab sebuah permintaan, membuat dua situs berbeda di satu alamat IP, dan tahu di lapis mana masalah "yang muncul malah situs lain" sebenarnya terjadi.

Artikel ini bukan panduan instalasi. Kalau kamu baru pertama kali memasang Nginx, mulai dari halaman Debian : Konfigurasi Web Server (Nginx). Di sini kita membedah proses keputusan di balik layar.

πŸ“ Konteks nyata

Bayangkan satu gedung dengan satu alamat. Tamu datang ke resepsionis, menyebut nama yang dituju, lalu diarahkan ke lantai yang tepat.

Nginx bekerja seperti resepsionis itu. Alamat gedungnya adalah IP dan port, nama yang disebut tamu adalah header Host, dan lantai tujuan adalah server block.

  • πŸ”₯ Kasus nyata: Sebuah SMK menggabungkan wiki, aplikasi ujian, dan situs profil sekolah di satu server. Saat "merapikan folder", seorang teknisi menghapus symlink di /etc/nginx/sites-enabled/. Ketiga domain langsung menampilkan halaman default Nginx selama dua hari, dan panitia menuduh DNS sekolah rusak. Penyebab sebenarnya ketahuan dalam 10 detik lewat nginx -T: konfigurasi yang dipakai Nginx memang tidak lagi memuat ketiga server block itu.

🧠 Konsep singkat

Nginx bukan program yang menyalakan satu utas (thread) untuk setiap pengunjung. Ada satu proses master yang membaca konfigurasi, lalu beberapa proses worker yang melayani koneksi.

Karena worker bekerja dengan model event, satu worker bisa menangani ribuan koneksi yang menunggu tanpa kehabisan utas. Analoginya: satu pramuniaga yang melayani banyak meja sekaligus, bukan satu pramuniaga yang berdiri diam di tiap meja.

πŸ”Ή Tiga lapis keputusan

Setiap permintaan HTTP melewati tiga pintu berurutan. Kalau satu pintu salah, gejala yang muncul bisa terlihat seperti masalah di pintu lain.

Lapis Yang dibaca Gejala kalau salah
Soket alamat IP dan port di listen koneksi ditolak, atau situs lain yang menjawab
Nama header Host lawan server_name muncul situs default, bukan situs yang dituju
Path URI lawan location 404, 403, atau file dari folder yang salah

Aturan praktisnya: buktikan lapis pertama dulu, jangan langsung mengubah isi halaman. Situs yang "salah tampil" hampir tidak pernah disebabkan oleh file HTML-nya.

πŸ”Ή Virtual host adalah server block

Satu blok server { ... } mewakili satu situs. Di dalamnya ada listen, server_name, dan aturan lain seperti root serta location.

Ada dua cara memisahkan situs:

  • Berbasis IP β€” tiap situs punya alamat IP sendiri. Boros, karena IP publik terbatas.
  • Berbasis nama β€” semua situs berbagi satu IP, dibedakan dari header Host. Inilah cara kerja hampir semua hosting.
  • πŸ“Š Angka penting: Satu IP publik bisa melayani ratusan nama domain. Yang membedakan hanya header Host, satu baris teks yang dikirim browser di setiap permintaan.

Untuk HTTPS, nama domain dibaca lebih awal lagi: saat handshake TLS lewat SNI, sebelum header HTTP dikirim. Karena itu sertifikat bisa dipilih per situs walau IP-nya sama.

πŸ”Ή default_server milik port, bukan nama

Ini sumber kebingungan paling sering. Dokumentasi resmi Nginx menyebut tegas: *default server adalah properti dari port listen, bukan properti server_name*.

Artinya:

  • Kalau tidak ada default_server, blok server pertama pada port itu yang jadi default.
  • Kalau header Host tidak cocok dengan nama mana pun, permintaan jatuh ke default server.
  • server_name _; yang sering ditempel dari internet bukan wildcard. Itu cuma nama domain tidak valid yang tidak akan pernah cocok dengan nama asli.

Catch-all yang benar adalah menggabungkan keduanya:

server {
    listen 8080 default_server;
    server_name _;
    return 444;
}

Kode 444 adalah kode non-standar milik Nginx: koneksi ditutup tanpa jawaban sama sekali. Fungsinya menolak permintaan yang datang langsung ke IP tanpa nama domain yang sah.

  • ⚠️ Hati-hati: Dua blok dengan default_server di port yang sama membuat Nginx menolak start dengan pesan duplicate default server. Tidak ada yang menang diam-diam, konfigurasinya memang batal dimuat.

πŸ”Ή Urutan pencocokan server_name

Kalau ada beberapa nama di port yang sama, Nginx mencari dengan urutan prioritas berikut, dan berhenti pada yang pertama cocok:

  1. Nama persis, misalnya wiki.lab.
  2. Wildcard berawalan bintang paling panjang, misalnya *.lab.
  3. Wildcard berakhiran bintang paling panjang, misalnya mail.*.
  4. Regex pertama yang cocok, sesuai urutan di file.

Nama persis disimpan di tabel hash, jadi pencariannya cepat. Regex dicek satu per satu, sehingga paling lambat dan tidak skalabel untuk jumlah nama besar.

  • πŸ“Š Angka penting: Kalau nama domain terlalu panjang untuk tabel hash bawaan, Nginx menolak start dengan pesan could not build server_names_hash, you should increase server_names_hash_bucket_size: 32. Solusinya menaikkan nilai itu ke pangkat dua berikutnya, misalnya 64.

Nama yang ditulis dua kali tidak membuat Nginx gagal start. Ia hanya memberi peringatan conflicting server name "...", ignored dan memakai yang pertama. Sisa bloknya jadi konfigurasi mati yang menipu saat dibaca.

πŸ”Ή Urutan pencocokan location

Setelah server block terpilih, Nginx memilih location untuk URI-nya. Aturannya berlapis, bukan dari atas ke bawah:

  1. Cari semua prefix, ingat yang paling panjang.
  2. Kalau prefix terpanjang memakai ^~, regex tidak dicek sama sekali.
  3. Kalau tidak, regex dicek berurutan dan yang pertama cocok menang.
  4. Kalau tidak ada regex yang cocok, pakai prefix terpanjang tadi.

Modifier = berarti harus sama persis dan pencarian langsung selesai. Inilah contoh resmi dari dokumentasi Nginx:

Permintaan Location yang menang
/ location = /
/index.html location /
/documents/document.html location /documents/
/images/1.gif location ^~ /images/
/documents/1.jpg location ~* \.(gif|jpg|jpeg)$

Perhatikan baris terakhir: /documents/1.jpg tetap masuk ke regex walau prefix /documents/ lebih spesifik. Itulah sebabnya urutan file tidak menentukan, dan sebabnya ^~ ada: untuk mengunci sebuah folder agar tidak direbut regex.

πŸ”Ή root dan alias bukan sinonim

root menempelkan URI ke path. alias mengganti bagian yang cocok.

Dengan root /data/w3; di dalam location /i/, permintaan /i/top.gif dilayani dari /data/w3/i/top.gif.

Dengan alias /data/w3/images/; di location /i/, permintaan yang sama dilayani dari /data/w3/images/top.gif β€” tanpa tambahan i/.

  • ⚠️ Hati-hati: alias bekerja sebagai penggantian teks. Kalau location /i/ dipasangkan alias /data/w3/images tanpa garis miring penutup, hasilnya /data/w3/images + top.gif = /data/w3/imagestop.gif. File tidak ada, halaman jadi 404, padahal folder dan filenya benar.

πŸ”Ή index, try_files, dan satu putaran tambahan

Kalau URI berakhir dengan garis miring, Nginx mencari file indeks sesuai direktif index. Bila index.html tidak ada tapi index.php ada, Nginx melakukan internal redirect ke /index.php lalu mencari location lagi dari awal.

Karena itu satu permintaan bisa berpindah location. Kalau hasilnya aneh, ingat bahwa location kedua yang menentukan, bukan yang pertama.

try_files memeriksa file berurutan dan memakai yang pertama ditemukan. Garis miring di akhir berarti memeriksa direktori, dan parameter terakhir adalah tujuan redirect internal atau kode error.

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

🧩 Istilah penting

Istilah Arti sederhana
Server block Satu blok server { } yang mewakili satu situs
Virtual host Istilah umum untuk situs yang berbagi satu server fisik
Header Host Nama domain yang diminta browser, dikirim di setiap permintaan
server_name Daftar nama yang dilayani sebuah server block
default_server Situs penampung bila tidak ada nama yang cocok
location Aturan berdasarkan potongan URI
root Folder dasar yang ditambahi URI
alias Path pengganti untuk location tertentu
try_files Daftar kandidat file yang dicoba berurutan
SNI Cara browser menyebut nama domain saat handshake TLS
Reload Memuat ulang konfigurasi tanpa memutus koneksi yang sedang jalan
Upstream Kumpulan server aplikasi di belakang Nginx

πŸ”§ Praktik: dua situs di satu server

Lab ini memakai port 8080 supaya tidak bentrok dengan web server lain yang mungkin sudah memakai port 80 di komputermu.

πŸ”Ή Langkah 1: potret keadaan awal

nginx -v
ss -lntp | grep -E ':80|:8080'
sudo nginx -T > /tmp/nginx-awal.txt
wc -l /tmp/nginx-awal.txt

nginx -T mencetak konfigurasi gabungan yang benar-benar dipakai, termasuk hasil include. Simpan potret ini; nanti kita bandingkan setelah menambah situs.

  • πŸ§ͺ Uji cepat: Kalau nginx -T gagal, jangan lanjut. Perbaikkan dulu error yang disebutkan, karena semua langkah berikutnya bergantung pada konfigurasi yang valid.

πŸ”Ή Langkah 2: siapkan dua web root

sudo mkdir -p /srv/www/wiki.lab /srv/www/ujian.lab
printf 'WIKI TKJ\n'  | sudo tee /srv/www/wiki.lab/index.html
printf 'UJIAN ONLINE\n' | sudo tee /srv/www/ujian.lab/index.html
sudo chown -R www-data:www-data /srv/www
sudo chmod 755 /srv/www /srv/www/wiki.lab /srv/www/ujian.lab

Dua folder, dua isi berbeda. Ini penting: kalau isinya sama, kamu tidak bisa membuktikan situs mana yang menjawab.

πŸ”Ή Langkah 3: tulis dua server block

server {
    listen 8080;
    server_name wiki.lab;

    root /srv/www/wiki.lab;
    index index.html;

    access_log /var/log/nginx/wiki.access.log;
    error_log  /var/log/nginx/wiki.error.log;
}

server {
    listen 8080;
    server_name ujian.lab;

    root /srv/www/ujian.lab;
    index index.html;

    access_log /var/log/nginx/ujian.access.log;
    error_log  /var/log/nginx/ujian.error.log;
}

Simpan sebagai /etc/nginx/sites-available/wiki-lab.conf dan /etc/nginx/sites-available/ujian-lab.conf. Pada paket Debian dan Ubuntu, folder sites-available adalah gudang konfigurasi, sedangkan sites-enabled adalah yang dibaca nginx.conf lewat include.

sudo ln -s /etc/nginx/sites-available/wiki-lab.conf  /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/ujian-lab.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t menguji sintaks tanpa mengubah apa pun. reload memuat konfigurasi baru dengan mulus: worker lama menyelesaikan permintaan yang sedang berjalan, worker baru memakai konfigurasi terkini.

  • πŸ’‘ Tips: Biasakan urutan nginx -t lalu reload, bukan restart. Restart memutus koneksi aktif dan tidak perlu untuk perubahan konfigurasi biasa.

πŸ”Ή Langkah 5: uji tanpa menyentuh DNS

curl -s http://127.0.0.1:8080/ -H "Host: wiki.lab"
curl -s http://127.0.0.1:8080/ -H "Host: ujian.lab"
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/

Baris pertama harus mencetak WIKI TKJ, baris kedua UJIAN ONLINE. Perintah ketiga sengaja tanpa Host yang cocok, jadi ia jatuh ke default server β€” yaitu blok pertama pada port 8080.

Kalau kamu ingin menguji seperti browser sungguhan tanpa mengubah /etc/hosts, pakai --resolve:

curl -s --resolve ujian.lab:8080:127.0.0.1 http://ujian.lab:8080/

πŸ”Ή Langkah 6: pasang penolak sebagai default

server {
    listen 8080 default_server;
    server_name _;
    return 444;
}

Simpan sebagai sites-available/tolak-lab.conf, buat symlink, lalu uji ulang:

sudo ln -s /etc/nginx/sites-available/tolak-lab.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
curl -sv -H "Host: tidak-ada.lab" http://127.0.0.1:8080/ 2>&1 | tail -3

Hasil yang diharapkan: koneksi ditutup tanpa balasan, dan curl melaporkan Empty reply from server. Permintaan ke wiki.lab dan ujian.lab tetap normal karena namanya cocok persis.

  • πŸ“Š Angka penting: Kode 444 tidak ada di standar HTTP. Browser hanya melihat koneksi terputus. Efek sampingnya: alat monitoring sederhana bisa melaporkan "server mati" padahal Nginx sehat dan sedang menolak.

πŸ”Ή Langkah 7: buktikan siapa yang menang di location

server {
    listen 8081;
    server_name peta.lab;
    root /srv/www/peta.lab;
    default_type text/plain;

    location = /            { return 200 "A-halaman-depan"; }
    location /              { return 200 "B-prefix-umum"; }
    location ^~ /gambar/    { return 200 "D-prefix-keras"; }
    location ~* \.(jpg|png)$ { return 200 "E-regex-gambar"; }
}

Uji tiga URI berikut:

curl -s -H "Host: peta.lab" http://127.0.0.1:8081/
curl -s -H "Host: peta.lab" http://127.0.0.1:8081/gambar/logo.jpg
curl -s -H "Host: peta.lab" http://127.0.0.1:8081/dokumen/logo.jpg

Hasilnya berurutan: A-halaman-depan, D-prefix-keras, E-regex-gambar. Sekarang hapus tanda ^~ dari blok gambar, reload, lalu ulangi permintaan kedua. Hasilnya berubah menjadi E-regex-gambar.

Itu bukti bahwa regex mengalahkan prefix, kecuali prefix dikunci dengan ^~.

πŸ”Ή Langkah 8: buktikan root berbeda dari alias

sudo mkdir -p /srv/www/peta.lab/isi/r
printf 'ROOT\n'  | sudo tee /srv/www/peta.lab/isi/r/top.txt
printf 'ALIAS\n' | sudo tee /srv/www/peta.lab/isi/top.txt

Tambahkan dua location ini ke server block tadi:

location /r/ { root  /srv/www/peta.lab/isi; }
location /a/ { alias /srv/www/peta.lab/isi/; }

Setelah reload, /r/top.txt mencetak ROOT dan /a/top.txt mencetak ALIAS. Keduanya menunjuk folder yang sama, tapi aturan penggabungan path-nya berbeda.

πŸ”Ή Langkah 9: bersihkan lab

sudo rm -f /etc/nginx/sites-enabled/wiki-lab.conf \
           /etc/nginx/sites-enabled/ujian-lab.conf \
           /etc/nginx/sites-enabled/tolak-lab.conf \
           /etc/nginx/sites-enabled/peta-lab.conf
sudo nginx -t && sudo systemctl reload nginx
sudo nginx -T | grep -c "server_name wiki.lab"

Angka terakhir harus 0. Kalau masih 1, symlink lain masih menunjuk file yang sama dan situsnya belum benar-benar dilepas.

🏭 Dipakai di dunia kerja

  • Sekolah: satu server untuk wiki, aplikasi ujian, dan situs profil. Server block memisahkan ketiganya tanpa perlu tiga IP publik atau tiga mesin.
  • Kantor dan UMKM: Nginx berdiri di depan aplikasi kasir atau absensi sebagai reverse proxy, sehingga aplikasi internal tidak diekspos langsung ke internet.
  • Hosting bersama: ribuan domain berbagi satu IP, dibedakan lewat server_name. Inilah alasan satu IP bisa melayani banyak pelanggan.
  • ISP dan warnet: portal login, halaman status, dan billing sering berada di server yang sama dengan nama berbeda.
  • Industri dan e-commerce: dua server block atau upstream berbobot dipakai untuk mengarahkan sebagian trafik ke versi baru sebelum dirilis penuh.
  • Operasional DevOps: konfigurasi situs disimpan di git, diuji dengan nginx -t di pipeline, lalu di-reload tanpa memutus pengguna.

βœ… Verifikasi

Perintah Hasil yang diharapkan
sudo nginx -t syntax is ok dan test is successful
sudo nginx -T konfigurasi gabungan memuat semua server block aktif
ss -lntp | grep 8080 ada proses nginx yang mendengarkan port itu
curl -H "Host: wiki.lab" isi situs wiki, bukan halaman default
curl tanpa Host cocok ditolak 444 atau masuk default server yang memang disengaja
tail /var/log/nginx/wiki.access.log baris permintaan uji tercatat di log situs yang benar
sudo systemctl is-active nginx active
sudo nginx -T | grep server_name daftar nama sesuai rencana, tidak ada duplikat

⚠️ Kesalahan umum & troubleshooting

Gejala atau pesan Artinya dan tindakan
duplicate default server for 0.0.0.0:8080 ada dua default_server di port sama; hapus salah satu
conflicting server name "...", ignored nama ditulis di dua blok; yang pertama menang, sisanya mati
open() ".../sites-enabled/x" failed (2: No such file) symlink menunjuk file yang sudah dihapus; buat ulang atau hapus symlink
bind() to 0.0.0.0:80 failed (98: Address already in use) port dipakai Apache atau Nginx lain; cek dengan ss -lntp
directory index of "/srv/www/..." is forbidden tidak ada file index dan autoindex mati; benar, bukan bug
404 padahal file ada root atau alias salah, sering karena garis miring penutup
413 Request Entity Too Large unggahan melebihi client_max_body_size bawaan 1 MB
could not build server_names_hash naikkan server_names_hash_bucket_size ke pangkat dua berikutnya
reload sukses tapi situs tak berubah file yang diedit tidak ter-include; buktikan dengan nginx -T
unexpected end of file, expecting "}" kurung kurawal tidak seimbang; cek blok yang terakhir diedit
502 Bad Gateway upstream mati atau alamatnya salah; ini lapis aplikasi, bukan lapis nama

πŸ” Catatan keamanan & etika

  • Jangan menaruh web root di dalam /etc/nginx. Konfigurasi dan isi situs harus dipisah agar tidak ada file konfigurasi yang bisa diunduh.
  • Jangan chmod 777 folder web. Cukup 755 untuk folder dan 644 untuk file, dengan pemilik www-data.
  • Jangan simpan .git, .env, backup.zip, atau dump database di web root. Nginx menyajikan file apa adanya, tanpa bertanya apakah itu rahasia.
  • Matikan autoindex kecuali untuk folder yang memang publik. Daftar file yang terbuka bisa membeberkan struktur internal.
  • server_tokens off; menyembunyikan nomor versi Nginx dari header balasan. Kecil, tapi mempersulit pemindaian otomatis.
  • Perlakukan nginx -T sebagai dokumen internal: isinya path, nama host, dan alamat upstream. Jangan tempel mentah-mentah ke grup chat.
  • Uji konfigurasi di lab, bukan di server produksi. Satu default_server ganda bisa membuat seluruh situs berhenti dimuat saat reload.

πŸ“Œ Kesimpulan

Nginx memilih situs lewat tiga lapis: port, nama, lalu path. Virtual host hanyalah nama lain dari server block, dan default_server adalah milik port, bukan milik nama.

Kalau ada yang salah tampil, periksa berurutan: apakah port benar, apakah Host cocok dengan server_name, baru apakah location dan root menunjuk tempat yang tepat.

Langkah berikutnya: tambahkan HTTPS pada salah satu situs, lalu jadikan Nginx reverse proxy di depan aplikasi. Di situ lapis keempat muncul β€” upstream β€” dan cara berpikirnya tetap sama.

πŸ”— Materi terkait

πŸ“š Referensi