Sejak pertama kali saya menggunakan [**Nginx**](https://nginx.org/) di pertengahan tahun 2011 lalu, Nginx langsung menjadi _web server_ favorit saya. [Apache](https://httpd.apache.org/) yang sebelumnya merupakan _"standard" web server_ di sistem operasi Linux sedikit demi sedikit mulai saya tinggalkan.
Seiring berjalannya waktu, beberapa _web server_ baru mulai bermunculan, seperti [Caddy](https://caddyserver.com/) dan [Traefik](https://traefik.io/traefik/). Sebagai seorang _system administrator_, tentu saja saya pernah mencoba menggunakannya, meskipun hanya sampai batas di penggunaan projek pribadi.
Namun, hati saya sepertinya selalu kembali ke Nginx. Aplikasi, _service_, atau **apapun itu yang bisa saya _expose_ melalui Nginx, akan saya _expose_ menggunakan Nginx**. Mungkin karena saya sudah terlalu nyaman dengan konfigurasi dan pengalaman menyenangkan bersama Nginx. XD
## _My use case_
Karena saya memiliki **IPv4 yang sangat terbatas**, saya banyak menggunakan Nginx sebagai _reverse proxy_ untuk _service-service_ yang tidak memiliki IP publik (VM dengan jaringan lokal / internal). Hal ini sangat membantu menghemat alokasi IP publik. Di kasus ini, saya banyak bermain dengan `proxy_cache` dan `http upstream` untuk mengimplementasikan _load balancing_ ataupun _failover_.
Ketika saya masih sering membuat program menggunakan **PHP**, saya menggunakan Nginx dan PHP-FPM tanpa adanya Apache (`.htaccess`) dibelakangnya. Jadi saya sering bermain dengan Nginx `rewrite` dan `fastcgi_cache`. Saat saya mulai membuat aplikasi menggunakan **Rust** dan **Go**, Nginx selalu bertugas sebagai _reverse proxy_ sekaligus melakukan _SSL termination_.
Selain HTTP _reverse proxy_, saya kadang menggunakan _module_ Nginx `stream` untuk TCP, UDP, bahkan _Unix socket_ data stream.
Mengenai _monitoring traffic_, saya selalu menggunakan [**Nginx VTS module**](https://github.com/vozlt/nginx-module-vts). Sudah tersedia [nginx-vts-exporter](https://github.com/sysulq/nginx-vts-exporter) untuk [Prometheus](https://prometheus .io/) yang sangat mudah dioperasikan untuk memproses data dari Nginx VTS module. Sedangkan untuk _logging_, beberapa log untuk _virtual host_ yang saya nilai krusial dikirimkan secara _real-time_ ke **remote syslog server**.
Sempurna sudah, semua fitur yang saya butuhkan terpenuhi oleh Nginx. Dan saatnya saya mulai mendokumentasikan proses instalasi dan konfigurasi untuk memenuhi apa yang saya butuhkan diatas.
Saya memiliki open-source project {{<bs/alert-link"nginx-kickstart""https://github.com/ditatompel/nginx-kickstart">}} (boilerplate) untuk mempermudah menginstall Nginx dari repositori officialnya dan mengkompile Nginx VTS module di FRESH Debian 12 atau Ubuntu 22.04 server.
Dokumentasi ini dibuat untuk **Debian 12** dan **Ubuntu 22.04**, dan saya menggunakan official repositori dari Nginx, bukan repositori bawaan dari distro.
Pertama dan utama, selalu pastikan sistem dalam keadaan _up-to-date_ dengan menjalankan perintah `sudo aptget update && sudo apt-get dist-upgrade`. Kemudian install _package-package_ yang dibutuhkan untuk installasi Nginx.
Jika ada _virtual host_ yang berada dibalik Cloudflare _reverse proxy_, sangat disarankan untuk menambahkan IP Cloudflare ke _trusted proxy_ di konfigurasi Nginx.
Buat _executable shell script_`/etc/nginx/cloudflare-ips.sh` berikut:
# if your vhost is behind CloudFlare proxy and you want your site only
# accessible from Cloudflare proxy, add this in your server{} block:
# if (\$cloudflare_ip != 1) {
# return 403;
# }" >> $CF_WHITELIST_PATH
nginx -t && systemctl reload nginx
# vim: set ts=4 sw=4 et:
```
Shell script diatas akan mendownload list IP milik Cloudflare untuk diproses dan disimpan di `/etc/nginx/snippets/cloudflare_*.conf`. Silahkan buat `cronjob` untuk menjalankan script tersebut secara berkala (per minggu / per bulan).
Untuk konfigurasi Nginx-nya, tambahkan konfigurasi berikut ke dalam `http{}` block di `/etc/nginx/nginx.conf`:
```nginx
http {
# ...
# Cloudflare IPs
################
include /etc/nginx/snippets/cloudflare_real_ips.conf;
real_ip_header X-Forwarded-For; # atau CF-Connecting-IP jika menggunakan Cloudflare
# cloudflare map
include /etc/nginx/snippets/cloudflare_whitelist.conf;
# ...
```
## Logging
Fitur _logging_ dapat memperlambat kinerja server (terutama karena **DISK I/O** yang tinggi) di situs dengan _traffic_ yang tinggi. Namun _logging_ juga sangat penting untuk memonitoring dan menganalisa aktifitas server.
### Log Format
Ada beberapa log format yang umum digunakan dan dapat diintegrasikan dengan aplikasi _3rd-party_, misalnya format `(V)COMMON` atau `(V)COMBINED`.
#### VCOMBINED format
Tambahkan konfigurasi berikut ke dalam `http{}` block:
```nginx
http {
# ...
# VCOMBINED log format style
log_format vcombined '$host:$server_port '
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
# ...
```
> Saya biasanya menggunakan log format `VCOMBINED` yang kemudian saya integrasikan dengan [GoAccess](https://goaccess.ditatompel.com/).
'"server_protocol": "$server_protocol", ' # request protocol, like HTTP/1.1 or HTTP/2.0
'"pipe": "$pipe", ' # "p" if request was pipelined, "." otherwise
'"gzip_ratio": "$gzip_ratio", '
'"geoip_country_code": "$geoip_country_code"'
'}';
# ...
}
```
### Conditional (dynamic) logging
Dengan `map`, dan `if`_keyword_, kita dapat menentukan apa saya yang akan di-log dan apa yang tidak. Misalnya, saya tidak melakukan _logging_ jika URI ada kata _"local"_ atau _User Agent_ mengandung kata _"Uptime-Kuma"_:
Bagi saya, sentraliasi log sangat mempermudah pekerjaan saya dalam melakukan analisa dan _troubleshooting_ server.
Di Nginx, kita dapat dengan mudah mengirimkan log ke _remote server_ secara _real-time_. Misalnya, kita dapat mengirimkan log ke **remote `rsyslog` server** (UDP) dengan contoh konfigurasi berikut:
**Nginx VTS module** tidak tersedia di Official Nginx repositori, sehingga kita tidak dapat menginstallnya menggunakan `apt`. Untuk mengkompile VTS module memerlukan `C`_compiler_, `git`, `libpcre`, `libssl`, dan `zlib`. Install _package_ yang dibutuhkan tersebut dengan menjalankan perintah:
Ini adalah bagian yang sangat penting, jika ingin menggunakan _dynamically linked module_, opsi mengkompile _module_ harus sama dengan Nginx _binary file_ yang akan digunakan, begitu pula dengan versi Nginx yang digunakan. Untuk mengetahui informasi yang kita butuhkan tersebut, jalankan perintah `nginx -V`. Contoh _output_:
Lalu _extract_ arsip Nginx _source code_ tersebut, kemudian masuk ke direktori didalamnya:
```shell
tar -xvzf nginx-1.26.0.tar.gz
cd nginx-1.26.0
```
Kemudian, clone repositori `vozlt/nginx-module-vts` dan gunakan [rilis tag terakhir](https://github.com/vozlt/nginx-module-vts/tags). Saat artikel ini dibuat, rilis tag terakhir adalah `v0.2.2`, maka:
Sebagai referensi konfigurasi akhir, silahkan lihat di repositori [https://github.com/ditatompel/nginx-kickstart/tree/main/etc/nginx](https://github.com/ditatompel/nginx-kickstart/tree/main/etc/nginx).