Compile dari Source

Compile Nginx dari Source #

Bagi sebagian besar administrator sistem, memasang Nginx melalui manajer paket (apt atau dnf) atau menggunakan container Docker sudah lebih dari cukup untuk memenuhi kebutuhan operasional sehari-hari. Binary bawaan tersebut umumnya sudah dikompilasi dengan modul-modul standar yang paling sering digunakan.

Namun, ada kalanya kita dihadapkan pada skenario khusus yang menuntut kita untuk membangun Nginx secara manual dari kode sumbernya (compile from source). Kompilasi manual memberi kita kontrol mutlak atas fitur apa saja yang ingin dimasukkan ke dalam Nginx, memungkinkan kita menambahkan modul pihak ketiga yang tidak didukung secara resmi, serta mengoptimalkan performa binary agar selaras dengan arsitektur CPU server kita. Artikel ini memandu kita melalui seluruh proses kompilasi hulu, integrasi modul eksternal, pembuatan service systemd, hingga prosedur pembaruan versi tanpa downtime (hot upgrade).

Kapan Kita Perlu Melakukan Kompilasi Manual? #

Membangun Nginx dari kode sumber menuntut komitmen pemeliharaan (maintenance) yang lebih tinggi karena kita harus melacak rilis keamanan baru dan melakukan kompilasi ulang secara manual untuk menambal celah keamanan. Oleh karena itu, kita hanya perlu memilih jalur ini jika menghadapi kebutuhan spesifik berikut:

  • Dukungan Modul Pihak Ketiga: Kita perlu menyisipkan modul kustom yang ditulis oleh komunitas, seperti modul kompresi Brotli Google (ngx_brotli), modul keamanan Web Application Firewall (ModSecurity), atau modul autentikasi LDAP (nginx-auth-ldap).
  • Pengerasan Keamanan Maksimal: Kita ingin menonaktifkan modul bawaan Nginx yang tidak digunakan (seperti modul mail proxy atau modul auto-index) untuk memperkecil ukuran biner dan meminimalkan celah serangan keamanan (attack surface).
  • Optimasi Spesifik Hardware: Kita ingin mengompilasi biner dengan flag optimasi CPU khusus (seperti instruksi AVX/AVX2 untuk server modern) untuk mempercepat proses kompresi dan enkripsi SSL/TLS.
  • Kecocokan Library Kustom: Kita ingin menautkan (link) Nginx ke versi library kriptografi eksternal yang sangat spesifik (misalnya, menautkan Nginx secara statis ke BoringSSL demi mendapatkan fitur enkripsi terbaru sebelum didukung secara resmi oleh OpenSSL bawaan OS).

Sebelum melangkah lebih jauh, kita dapat memeriksa modul apa saja yang sudah aktif pada biner Nginx bawaan sistem kita dengan perintah:

nginx -V 2>&1 | tr ' ' '\n' | grep module

Alur Kerja Kompilasi Manual #

Proses kompilasi secara sistematis melewati tiga tahap utama di bawah ini:

flowchart TD
    Start["Mulai Kompilasi Manual"] --> Prep["1. Pasang Build Tools & Dependensi <br> (GCC, Make, OpenSSL, PCRE, zlib)"]
    Prep --> Download["2. Unduh & Ekstrak Source Code Nginx <br> (Serta verifikasi GPG signature)"]
    Download --> Config{"3. Jalankan ./configure <br> dengan Opsi Flags & Modul"}
    
    Config -->|"Setup Konfigurasi Sukses"| Build["4. Jalankan 'make' <br> (Kompilasi kode C menjadi binary)"]
    Config -->|"Gagal (Missing Dependency)"| Prep
    
    Build --> Install["5. Jalankan 'sudo make install' <br> (Salin binary & config ke direktori tujuan)"]
    Install --> Setup["6. Buat Akun Sistem 'nginx' <br> & Berkas nginx.service Systemd"]
    Setup --> Done["Selesai: Nginx Siap Dijalankan"]
    
    style Config stroke:#f57c00,stroke-width:2px
    style Build stroke:#0288d1,stroke-width:2px
    style Install stroke:#388e3c,stroke-width:2px

Tahap 1: Memasang Dependensi Sistem Operasi #

Nginx ditulis menggunakan bahasa pemrograman C. Oleh karena itu, kita harus memasang perkakas compiler GCC (GNU Compiler Collection), utilitas pembangun make, serta beberapa library pengembangan yang dibutuhkan oleh fitur-fitur core Nginx.

Pustaka-pustaka inti yang wajib dipasang meliputi:

  1. PCRE (Perl Compatible Regular Expressions): Dibutuhkan oleh modul HTTP Core dan Rewrite untuk memproses ekspresi reguler pada blok konfigurasi location dan aturan pengalihan URL.
  2. zlib: Dibutuhkan oleh modul Gzip untuk melakukan kompresi data HTTP sebelum dikirimkan ke browser klien.
  3. OpenSSL: Dibutuhkan oleh modul SSL/TLS untuk menangani koneksi enkripsi HTTPS aman.

Kita dapat memasang seluruh dependensi tersebut di distribusi kita masing-masing:

Pada Ubuntu / Debian: #

sudo apt update
sudo apt install -y \
    build-essential \
    libpcre3 libpcre3-dev \
    zlib1g zlib1g-dev \
    libssl-dev \
    libgd-dev \
    git wget

Pada CentOS Stream / Rocky / AlmaLinux: #

sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y \
    pcre pcre-devel \
    zlib zlib-devel \
    openssl openssl-devel \
    gd gd-devel \
    git wget

Tahap 2: Mengunduh dan Memverifikasi Source Code #

Kita harus mengunduh file arsip kode sumber Nginx dari situs resmi. Kita disarankan memilih versi Stable terbaru untuk keperluan server produksi.

# Pindah ke direktori temporer
cd /tmp

# Unduh arsip source code Nginx (ganti versi sesuai rilis stable terbaru)
wget https://nginx.org/download/nginx-1.26.1.tar.gz

# Unduh berkas tanda tangan kriptografi (.asc) untuk verifikasi
wget https://nginx.org/download/nginx-1.26.1.tar.gz.asc

Demi alasan keamanan, kita harus memverifikasi integritas berkas arsip yang diunduh untuk menjamin bahwa kode tersebut asli dari tim Nginx dan tidak mengandung kode jahat tersembunyi:

# Impor kunci publik PGP resmi milik tim pengembang Nginx
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62

# Lakukan verifikasi tanda tangan digital pada arsip
gpg --verify nginx-1.26.1.tar.gz.asc nginx-1.26.1.tar.gz
# Pastikan output menunjukkan "Good signature"

Setelah integritas file terjamin, ekstrak arsip dan masuk ke direktori kode sumber tersebut:

tar -xzf nginx-1.26.1.tar.gz
cd nginx-1.26.1

Tahap 3: Konfigurasi Opsi Build (./configure) #

Langkah konfigurasi dilakukan dengan menjalankan skrip ./configure. Skrip ini bertugas memeriksa kesiapan sistem operasi kita, mendeteksi lokasi library dependensi, serta mendefinisikan lokasi direktori instalasi dan daftar modul Nginx yang ingin diaktifkan.

Berikut adalah contoh konfigurasi production-ready yang mengaktifkan enkripsi TLS, HTTP/2, pembacaan IP proxy asli, thread pool untuk optimasi I/O disk, serta streaming proxy:

./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_v3_module \
    --with-http_realip_module \
    --with-http_stub_status_module \
    --with-http_gzip_static_module \
    --with-threads \
    --with-stream \
    --with-stream_ssl_module \
    --with-compat

Penjelasan Parameter Utama Opsi Konfigurasi: #

  • --prefix=/etc/nginx: Menentukan direktori dasar tempat seluruh berkas konfigurasi Nginx akan diletakkan.
  • --sbin-path=/usr/sbin/nginx: Menentukan lokasi berkas biner executable Nginx yang akan diproduksi.
  • --user=nginx dan --group=nginx: Menentukan kredensial akun sistem non-privileged yang akan digunakan oleh worker process untuk menangani koneksi klien.
  • --with-http_v3_module: Mengaktifkan modul dukungan untuk HTTP/3 berbasis protokol transport UDP (QUIC).
  • --with-threads: Mengaktifkan fitur Thread Pools yang membebaskan worker process utama dari hambatan tugas I/O disk yang lambat.
  • --with-compat: Mengaktifkan kompatibilitas biner tingkat tinggi. Flag ini sangat penting karena memungkinkan kita memuat modul dinamis pihak ketiga (.so files) di masa depan tanpa perlu mengompilasi ulang seluruh biner inti Nginx.

Tahap 4: Menambahkan Modul Pihak Ketiga (Studi Kasus: Brotli) #

Brotli adalah algoritma kompresi data modern yang dikembangkan oleh Google, menawarkan rasio kompresi yang jauh lebih padat dibandingkan Gzip tradisional tanpa membebani CPU secara berlebihan. Kita akan menggunakan Brotli sebagai contoh bagaimana menyisipkan modul eksternal ke dalam proses kompilasi Nginx.

Pertama, kita harus mengunduh repositori modul ngx_brotli dari GitHub beserta seluruh submodulnya:

cd /tmp
git clone --recurse-submodules -j8 https://github.com/google/ngx_brotli.git

Opsi A: Mengompilasi Modul Secara Statis (Static Module) #

Modul statis akan digabungkan secara permanen di dalam berkas biner utama Nginx. Ini membuat proses deployment menjadi sangat praktis karena kita hanya memiliki satu file biner tunggal.

Kembali ke direktori source code Nginx dan jalankan ./configure dengan menambahkan parameter --add-module:

cd /tmp/nginx-1.26.1

# Jalankan konfigurasi dengan menyertakan modul eksternal
./configure [masukkan opsi-opsi konfigurasi dari Tahap 3 di atas] \
    --add-module=/tmp/ngx_brotli

Opsi B: Mengompilasi Modul Secara Dinamis (Dynamic Module) #

Modul dinamis akan dikompilasi menjadi berkas pustaka terpisah berakhiran .so. Pendekatan ini sangat disukai karena kita dapat mengaktifkan atau menonaktifkan modul tersebut di file konfigurasi tanpa perlu menyentuh biner inti Nginx.

Gunakan parameter --add-dynamic-module:

cd /tmp/nginx-1.26.1

./configure [masukkan opsi-opsi konfigurasi dari Tahap 3 di atas] \
    --add-dynamic-module=/tmp/ngx_brotli

Tahap 5: Eksekusi Pembangunan Biner (make & make install) #

Setelah konfigurasi ./configure berhasil diselesaikan tanpa error, kita siap membangun biner dengan perintah make. Kita dapat mempercepat waktu kompilasi dengan menggunakan parameter -j yang disesuaikan dengan jumlah core CPU yang dimiliki server kita:

# Kompilasi kode sumber menggunakan semua core CPU yang tersedia
make -j$(nproc)

Proses kompilasi akan menghasilkan berkas biner di dalam direktori objs/nginx. Kita dapat langsung memasangnya ke direktori tujuan sistem operasi kita dengan perintah:

# Salin biner dan struktur folder konfigurasi ke sistem
sudo make install

Tahap 6: Konfigurasi Systemd Service Custom #

Setelah kita melakukan make install, Nginx telah terpasang di sistem kita, tetapi manajer proses systemd belum mengetahui keberadaan layanan Nginx baru ini karena tidak ada pembuatan service file otomatis.

Kita harus membuat akun sistem khusus untuk keamanan terlebih dahulu, lalu menulis berkas unit service secara manual.

# Buat akun sistem khusus nginx jika belum ada di sistem
sudo useradd --system --no-create-home --shell /sbin/nologin nginx

# Buat direktori log dan berikan hak milik ke user nginx
sudo mkdir -p /var/log/nginx
sudo chown -R nginx:nginx /var/log/nginx

Selanjutnya, buat berkas unit service systemd:

sudo nano /etc/systemd/system/nginx.service

Isi berkas tersebut dengan konfigurasi unit berikut yang telah dilengkapi dengan fitur Security Sandboxing tingkat kernel Linux untuk membatasi hak akses biner Nginx:

[Unit]
Description=nginx - high performance web server
Documentation=https://nginx.org/en/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
# Uji konfigurasi sebelum service dijalankan
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
# Jalankan Master process
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
# Kirim sinyal HUP (1) untuk reload aman
ExecReload=/bin/kill -s HUP $MAINPID
# Kirim sinyal TERM (15) untuk graceful stop
ExecStop=/bin/kill -s TERM $MAINPID
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Mengaktifkan dan Menjalankan Service Baru: #

# Muat ulang systemd agar mendeteksi berkas service baru kita
sudo systemctl daemon-reload

# Aktifkan autostart saat boot
sudo systemctl enable nginx

# Jalankan service Nginx
sudo systemctl start nginx

# Periksa status layanan
sudo systemctl status nginx

Memuat Modul Dinamis Brotli (Jika Memilih Opsi Dinamis) #

Jika kita mengompilasi Brotli sebagai modul dinamis, berkas .so akan disalin ke /usr/lib64/nginx/modules/ atau direktori modul yang kita tentukan. Kita harus memuat modul tersebut di baris paling atas berkas konfigurasi utama /etc/nginx/nginx.conf:

# /etc/nginx/nginx.conf
# Muat modul dinamis di awal berkas sebelum blok events/http

load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

events {
    worker_connections 1024;
}

http {
    # Konfigurasi kompresi Brotli di dalam blok http
    brotli on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/javascript application/json image/svg+xml;
}

Prosedur Hot Upgrade (Zero-Downtime Upgrade) #

Salah satu keunggulan luar biasa dari arsitektur proses Nginx adalah kemampuannya melakukan peningkatan versi biner (upgrade binary) tanpa memutus satu pun koneksi aktif klien yang sedang terhubung ke server kita. Proses ini dikenal sebagai Hot Upgrade.

Berikut adalah alur bagaimana Master Process lama melahirkan Master Process baru dan mentransfer tanggung jawab penanganan soket port secara transparan:

sequenceDiagram
    autonumber
    participant K as Klien / Internet
    participant MO as Master Process Lama (PID Lama)
    participant MN as Master Process Baru (PID Baru)
    
    Note over MO: Nginx Versi Lama Sedang Berjalan
    K->>MO: Kirim Request HTTP aktif
    Note over MO: Ganti berkas biner /usr/sbin/nginx dengan versi baru
    Admin->>MO: Kirim Sinyal USR2 (kill -USR2 PID_Lama)
    MO->>MN: Spawn Master Process Baru (Menggunakan biner baru)
    Note over MN: Master Baru mewarisi listening sockets dari Master Lama
    MN->>MN: Spawn Worker Process Baru (Mulai layani request baru)
    K->>MN: Request baru masuk & dilayani biner baru
    Admin->>MO: Kirim Sinyal WINCH (kill -WINCH PID_Lama)
    MO->>MO: Graceful shutdown Worker Process Lama
    Note over MO: Worker lama mati setelah menyelesaikan request aktif
    Admin->>MO: Kirim Sinyal QUIT (kill -QUIT PID_Lama)
    MO->>MO: Master Lama mati secara damai
    Note over MN: Hanya Nginx Versi Baru yang aktif melayani

Langkah-Langkah Eksekusi Hot Upgrade di Terminal: #

Saat kita ingin meningkatkan versi Nginx dari 1.26.1 ke 1.28.0 yang baru saja kita kompilasi:

# 1. Kompilasi versi Nginx baru di direktori temporer dengan opsi flags yang sama
# JANGAN jalankan 'make install' agar tidak menimpa biner aktif secara kasar.

# 2. Backup biner Nginx lama kita yang sedang berjalan
sudo cp /usr/sbin/nginx /usr/sbin/nginx.old

# 3. Salin biner baru hasil kompilasi untuk menggantikan biner lama
sudo cp objs/nginx /usr/sbin/nginx

# 4. Kirim sinyal USR2 ke master process lama
# Sinyal ini memerintahkan master lama untuk merename berkas PID menjadi nginx.pid.oldbin
# dan menjalankan master process baru menggunakan biner baru yang kita pasang di /usr/sbin/nginx
sudo kill -USR2 $(cat /var/run/nginx.pid)

# Periksa status proses, sekarang ada dua master process Nginx yang berjalan bersamaan:
# Satu master process lama dan satu master process baru yang masing-masing memiliki worker-nya.
ps aux | grep nginx

# 5. Kirim sinyal WINCH ke master process lama
# Sinyal ini memerintahkan master lama untuk menonaktifkan worker proses lamanya secara graceful
sudo kill -WINCH $(cat /var/run/nginx.pid.oldbin)

# 6. Pantau trafik server. Jika semua berjalan lancar tanpa ada keluhan dari klien,
# kirim sinyal QUIT ke master process lama untuk mematikan master lama sepenuhnya
sudo kill -QUIT $(cat /var/run/nginx.pid.oldbin)

Jika terjadi masalah setelah langkah 4 atau 5, kita dapat melakukan pembatalan (rollback) secara instan tanpa downtime:

# Jika terjadi error pada biner baru, aktifkan kembali worker lama
sudo kill -HUP $(cat /var/run/nginx.pid.oldbin)

# Kirim sinyal QUIT ke master baru untuk mematikannya
sudo kill -QUIT $(cat /var/run/nginx.pid)

# Kembalikan biner backup kita
sudo mv /usr/sbin/nginx.old /usr/sbin/nginx

Ringkasan #

  • Kompilasi dari source memberikan fleksibilitas mutlak untuk menyisipkan modul eksternal kustom (seperti ngx_brotli atau WAF) yang tidak tersedia di paket standar distro.
  • Pastikan dependensi inti (pcre, zlib, openssl) sudah terpasang sebelum menjalankan proses konfigurasi.
  • Gunakan flag --with-compat agar biner Nginx kita mendukung pemuatan modul dinamis (.so) tanpa recompile sistem inti di masa mendatang.
  • Buat berkas service systemd secara manual setelah menjalankan make install, lengkap dengan parameter keamanan sandbox seperti ProtectSystem=strict.
  • Lakukan hot upgrade menggunakan sinyal USR2, WINCH, dan QUIT untuk memperbarui biner Nginx secara langsung tanpa mengganggu kenyamanan pengguna akhir (zero-downtime).

← Sebelumnya: Docker   Berikutnya: Struktur File Config →

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