All Newbie, Semua Tentang Ilmu

Recent

Cara Setting Nginx Reverse Proxy untuk Banyak Domain

Satu VPS dengan satu IP publik bisa melayani banyak domain dan banyak aplikasi sekaligus. Nginx membaca nama domain dari SNI dan header Host, lalu meneruskan permintaan ke aplikasi yang tepat di belakangnya — semuanya tanpa membuka port aplikasi ke internet.

Rak jaringan berisi switch dan patch panel dengan kabel LAN tertata, tempat trafik reverse proxy melewati satu titik masuk
Foto: Dsimic, CC BY-SA 4.0, via Wikimedia Commons

Ringkasan singkat

  • Satu file konfigurasi per domain di sites-available.
  • Empat header wajib: Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto.
  • Tolak domain asing dengan default_server + return 444.
  • Uji dengan header Host sebelum DNS propagasi.

Yang perlu disiapkan

  • Nginx terpasang di Ubuntu 24.04.
  • Domain yang record A-nya sudah mengarah ke IP server (cek dig +short domain).
  • Aplikasi yang mendengarkan di localhost, misal port 3000 dan 8080.
  • Certbot untuk sertifikat TLS.

1. Pola direktori

Simpan satu file per domain agar mudah dilacak:

sudo mkdir -p /var/www/app1
sudo nano /etc/nginx/sites-available/app1.contoh.com

Aktifkan dengan symlink, bukan dengan menyalin file. Dengan begitu hanya ada satu sumber kebenaran:

sudo ln -s /etc/nginx/sites-available/app1.contoh.com /etc/nginx/sites-enabled/
Nginx reverse proxy mengarahkan tiga domain ke upstream berbedaPenggunaHTTPSNginx :443SNI + Hostsatu IP publikapp1.contoh.comupstream 127.0.0.1:3000api.contoh.comupstream 127.0.0.1:8080statis.contoh.comroot /var/www
Diagram: Nginx reverse proxy mengarahkan tiga domain ke upstream berbeda

2. Reverse proxy dasar

server {
    listen 80;
    server_name app1.contoh.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Empat header itu bukan formalitas. Tanpa X-Forwarded-For, aplikasi mencatat IP Nginx untuk semua pengguna; tanpa X-Forwarded-Proto, aplikasi mengira koneksi masih HTTP dan bisa menghasilkan redirect loop.

3. Domain kedua dan seterusnya

server {
    listen 80;
    server_name api.contoh.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Tambahkan satu blok server per domain. Jangan menumpuk beberapa server_name dengan tujuan berbeda dalam satu blok — hasilnya sulit diprediksi saat ada perubahan.

4. WebSocket

Aplikasi realtime memerlukan header upgrade. Tambahkan di level http (biasanya di /etc/nginx/nginx.conf):

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Lalu di dalam location:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

5. Tolak domain asing

Tanpa blok default, permintaan ke IP langsung atau domain lain akan dilayani situs pertama yang aktif. Itu membuat trafik tak dikenal masuk ke aplikasi kita:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

Kode 444 adalah kode internal Nginx: koneksi ditutup tanpa respons. Lebih hemat daripada mengirim 404 ke pemindai port.

6. Uji konfigurasi dan muat ulang

sudo nginx -t
sudo systemctl reload nginx
curl -I http://app1.contoh.com
curl -I http://api.contoh.com

nginx -t harus lolos sebelum reload. Reload gagal tidak mematikan Nginx, tetapi perubahanmu juga tidak berlaku dan itu mudah tertukar dengan "konfigurasi tidak bekerja".

7. Pasang TLS untuk semua domain

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d app1.contoh.com -d api.contoh.com

Satu sertifikat bisa memuat beberapa nama (SAN). Kalau domain bertambah, cukup jalankan Certbot lagi dengan -d tambahan; Certbot akan memperluas sertifikat yang ada.

8. Batas ukuran unggahan dan timeout

client_max_body_size 25m;
proxy_read_timeout 120s;
proxy_send_timeout 120s;

Aplikasi yang menerima unggahan besar akan gagal dengan 413 Request Entity Too Large kalau batas ini tidak dinaikkan. Sebaliknya, jangan set ke 0 (tanpa batas) karena membuka jalan penyalahgunaan disk.

9. Mengarahkan ke container Docker

Kalau aplikasi berjalan di container, ikat port ke localhost agar tidak melewati firewall:

docker run -d --name app1 -p 127.0.0.1:3000:3000 app1:latest

Lalu proxy_pass http://127.0.0.1:3000; bekerja seperti biasa, dan port itu tidak terbuka ke internet.

10. Kompresi dan cache aset statis

gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;

location ~* \.(css|js|jpg|png|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

Aset statis sebaiknya dilayani langsung oleh Nginx, bukan diteruskan ke aplikasi. Satu aturan ini biasanya memangkas waktu render halaman secara signifikan karena browser tidak lagi mengunduh ulang berkas yang sama.

11. Log terpisah per domain

access_log /var/log/nginx/app1.access.log;
error_log  /var/log/nginx/app1.error.log;

Saat satu domain bermasalah, log gabungan membuat diagnosis lambat. Dengan file terpisah, kamu bisa langsung melihat permintaan dan error milik domain itu saja, lalu memutar log dengan logrotate agar disk tidak penuh.

12. Menguji tanpa menunggu DNS

Propagasi DNS bisa berjam-jam. Uji server block lebih dulu dengan mengirim header Host langsung ke localhost:

curl -I -H "Host: app1.contoh.com" http://127.0.0.1

Balasan 200 dengan halaman yang benar berarti konfigurasi sudah siap dan sisa masalahnya hanya DNS. Untuk HTTPS, gunakan --resolve agar nama domain diarahkan ke localhost tanpa mengubah DNS:

curl -I --resolve app1.contoh.com:443:127.0.0.1 https://app1.contoh.com

13. Menonaktifkan satu domain

sudo rm /etc/nginx/sites-enabled/app1.contoh.com
sudo nginx -t && sudo systemctl reload nginx

Hapus symlink, bukan file aslinya, supaya konfigurasinya masih bisa diaktifkan kembali tanpa mengetik ulang.

Masalah yang sering muncul

GejalaPenyebabSolusi
502 Bad GatewayAplikasi mati atau port salahss -lntp | grep 3000, cek log aplikasi
504 Gateway TimeoutAplikasi lambat, proxy menyerahNaikkan proxy_read_timeout, perbaiki performa aplikasi
413 Request Entity Too LargeBatas unggahan default 1 MBclient_max_body_size
IP pengguna selalu 127.0.0.1Header tidak diteruskanSet X-Real-IP dan X-Forwarded-For
WebSocket langsung terputusHeader upgrade tidak adaTambahkan map dan Connection
Domain lain ikut tampilTidak ada default_serverTambahkan blok return 444

Pertanyaan yang sering diajukan

Berapa domain yang bisa dilayani?

Batasan praktisnya RAM dan jumlah sertifikat, bukan Nginx. Puluhan domain di satu VPS kecil adalah hal biasa.

Perlu satu server block per aplikasi atau per domain?

Per domain. Kalau satu domain punya beberapa path ke aplikasi berbeda, gunakan location /api/ dengan proxy_pass sendiri.

Apakah Nginx menggantikan firewall?

Tidak. Nginx mengatur trafik HTTP; pembatasan port tetap tugas UFW.

Bagaimana melihat domain mana yang menerima trafik?

sudo tail -f /var/log/nginx/access.log




0 comments:

Post a Comment