
Pada grafik benchmark di atas kita bisa lihat hasil dari tes request concurrency 1000, Nginx + PHP-FPM yang biasa saya gunakan ternyata masih kalah dengan Nginx Unit. Nginx Unit menjadi juara ketiga, setelah FrankenPHP (worker mode) dan Swoole. tapi kalau pakai Swoole kita bakal harus tulis ulang kode program kita karena dia konsepnya non-blocking I/O seperti NodeJS. Jadi kurang cocok untuk project PHP yang sudah jadi.
Jadi dua kandidat PHP runtime yang paling menarik buat saya ulik adalah Nginx Unit dan FrankenPHP. Namun pada artikel ini saya akan bahas dulu tentang cara install dan konfigurasi Nginx Unit dan PHP di komputer Ubuntu. Disini saya menggunakan Ubuntu 24.04 Noble Numbat. Dokumentasi lengkap Nginx Unit bisa dilihat di https://unit.nginx.org/ dan repo Githubnya di https://github.com/nginx/unit/.
Install PHP
Ini task standar ya, install dulu PHP dan Composer sebagaimana biasanya. Tapi tidak perlu install php-fpm karena kita tidak perlu itu di Nginx Unit.
`sudo add-apt-repository -y ppa:ondrej/php
sudo apt-get install -y php8.3-dev php8.3-embed \
php8.3-bcmath php8.3-cli php8.3-common php8.3-curl \
php8.3-gd php8.3-intl php8.3-mbstring php8.3-mysql php8.3-pgsql \
php8.3-redis php8.3-soap php8.3-sqlite3 php8.3-xml php8.3-zip
curl -sLS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/bin/ --filename=composer`
Install Nginx Unit
Daftarkan paket repositori ke sistem
`wget https://raw.githubusercontent.com/nginx/unit/master/tools/setup-unit && chmod +x setup-unit
sudo ./setup-unit repo-config`
Install nginx-unit
sudo apt install unit
Install unit-php
Nginx Unit mendukung runtime untuk banyak bahasa pemrograman, diantaranya Go, JavaScript (Node.js), Java, Perl, PHP, Python, Ruby dan WebAssembly. Untuk sekarang saya akan install untuk PHP saja
`sudo apt install unit-dev unit-php
restart unit setelah menginstal module
sudo systemctl restart unit`
Konfigurasi Nginx Unit untuk PHP
Nginx Unit tidak seperti Nginx yang biasa yang konfigurasinya disimpan di dalam file. Kita mengatur konfigurasi di Nginx Unit secara dinamis via HTTP menggunakan RESTful JSON API. Di satu sisi ini hal yang ga bisa, tapi di sisi lain cara ini bikin pengaturan lebih fleksibel sehingga pembaharuan konfigurasi dapat dilakukan tanpa ada jeda gangguan karena kesalahan konfigurasi.
Untuk melihat konfigurasi yang sudah terpasang jalankan perintah ini:
sudo curl --unix-socket /var/run/control.unit.sock localhost
Maka akan muncul json configuration semisal ini:
{
"certificates": {},
"js_modules": {},
"config": {
"listeners": {},
"routes": [],
"applications": {}
},
"status": {
"modules": {
"php": {
"version": "8.3.6",
"lib": "/usr/lib/unit/modules/php.unit.so"
}
},
"connections": {
"accepted": 0,
"active": 0,
"idle": 0,
"closed": 0
},
"requests": {
"total": 0
},
"applications": {}
}
}
Ada 3 pengaturan utama di Unit, diantaranya certificates
untuk managemen sertifikat SSL, config
untuk managemen konfigurasi, dan status
untuk statistik penggunaan unit.
Di bagian status
kita melihat sudah tampil modul yang terinstal yakni php.
Bila kita hanya ingin mengecek pengaturan config, maka kita dapat memanggil dengan perintah seperti ini
sudo curl --unix-socket /var/run/control.unit.sock localhost/config
Maka nanti yang tampil hanyak pengaturan config saja
{
"listeners": {},
"routes": [],
"applications": {}
}
Setup Aplikasi PHP
Saya akan pasang satu aplikasi sederhana menggunakan framework CodeIgniter sebagai contoh. Saya akan menyimpan folder projectnya di /var/development/. Kamu bebas mau simpan dimana saja, tidak mesti di /var/www/ karena kita tidak pakai nginx atau apache lagi.
`# Buat folder
sudo mkdir -p /var/development
Set folder permission menjadi 775
sudo chmod 775 /var/development -R
Set folder owner supaya group unit bisa mengakses folder
sudo chown $USER:unit /var/development -R
cd /var/development
Install aplikasi CodeIgniter 4
composer create-project codeigniter4/appstarter myapp
Pastikan folder dan files project dapat diakses oleh unit
sudo chmod 775 myapp -R
sudo chown :unit myapp -R`
Sekarang kita akan memasang konfigurasi unit agar server dapat melayani rekues ke aplikasi kita. Kita buat dulu file konfigurasinya. Saya akan menyimpan file konfigurasi di dalam folder /var/development
`cd /var/development
nano unit.config.json`
Masukkan json berikut ke dalam file unit.config.json
{
"listeners": {
"*:80": {
"pass": "routes"
}
},
"routes": [
{
"match": {
"host": "localhost",
"uri": "!/index.php"
},
"action": {
"share": "/var/development/myapp/public$uri",
"fallback": {
"pass": "applications/myapp"
}
}
}
],
"applications": {
"myapp": {
"type": "php",
"root": "/var/development/myapp/public/",
"script": "index.php",
"processes": {}
}
}
}
Ada 3 key utama pada config di atas:
listeners
untuk mendefinisikan request domain dan port yang akan dipantau oleh unit. Pada json di atas kita mendaftarkan port 80 dari domain apapun (*) yang masuk. Request kemudian diserahkan ke bagian routes
untuk diproses lebih lanjut
routes
untuk mendefinisikan rute request ke program yang sesuai. Pada json di atas kita sudah mendaftarkan satu kondisi, bila request masuk dari domain localhost, maka action
-nya arahkan ke applications/myapp
applications
untuk mendefinisikan aplikasi yang akan melayani request yang sudah dirutekan ke aplikasi yang dimaksud. Pada bagian routes
kita mengarahkan request ke aplikasi myapp.
Setelah konfigurasi json disimpan di dalam file unit.config.json, jalankan perintah berikut ini untuk memasang konfigurasi ke unit
# Pastikan posisi terminal ada di dalam folder yang berisi unit.config.json
sudo curl -X PUT --data-binary @unit.config.json --unix-socket /var/run/control.unit.sock localhost/config
Bila hasil yang muncul adalah json dengan pesan { "success": "Reconfiguration done." }
berarti konfigurasi berhasil terpasang.
Untuk mengetes, buka http://localhost di browser, atau kalau kamu mencoba di server, jalankan perintah berikut untuk memanggil localhost
curl http://localhost
Perintah ini seharusnya akan mengembalikan html dari halaman welcome message CodeIgniter. Tandanya request ke http://localhost berhasil dilayani oleh Nginx Unit dan aplikasi myapp.