Bali, Indonesia
Insights

Disk VPS Penuh Gara-Gara error_log WordPress Membengkak Saat Diserbu Bot Scanner

October 29, 2026
0:00
Disk VPS tiba-tiba penuh, situs WordPress error, dan kamu yakin tidak ada yang upload file besar. Setelah dicari, ternyata pelakunya satu file bernama error_log di dalam folder situs, dan ukurannya sudah gigabyte. Penyebabnya biasanya bukan bug baru, tapi bot scanner yang terus mengetuk path plugin dan file yang tidak ada. Setiap ketukan itu meninggalkan beberapa baris error. Tulisan ini disusun seperti post-mortem: apa yang terlihat duluan, urutan investigasinya, momen penyebabnya ketemu, mitigasi sementara, lalu perbaikan supaya tidak terulang.
Gejala pertama jarang berbunyi "disk penuh". Yang muncul biasanya error database connection di WordPress, karena MySQL atau MariaDB berhenti atau gagal menulis. Bisa juga upload media gagal, session PHP tidak bisa ditulis, atau email tertahan karena MTA (mail transfer agent, seperti Exim atau Postfix) tidak bisa menulis ke queue. Efeknya juga merembet ke hal yang tidak kelihatan. Proses terjadwal seperti backup atau renewal sertifikat ikut gagal diam-diam. Pola ini pernah dibahas di artikel Certbot yang gagal renew karena disk dan inode habis. Dari sisi support, keluhan yang masuk sering berupa "web down" atau "email tidak masuk". Jarang ada yang langsung bilang "disk penuh". Karena itu, cek disk sebaiknya jadi salah satu langkah pertama, bukan langkah terakhir.
Langkah pertama adalah memastikan jenis "penuh"-nya. Ada dua kemungkinan: ruang byte yang habis, atau inode yang habis. Inode adalah slot metadata untuk tiap file. Kasus error_log membengkak hampir selalu soal byte, karena isinya satu file raksasa, bukan jutaan file kecil. Tetap cek keduanya supaya tidak salah arah. Setelah itu, persempit pencarian dari level direktori ke level file. Semua perintah di bawah ini read-only:
BASH
# ruang byte dan inode per filesystem
df -h
df -i

# direktori terbesar di /home (ganti ke /var/www kalau bukan server cPanel)
du -xh --max-depth=1 /home 2>/dev/null | sort -h | tail -n 15

# cari file error_log yang ukurannya di atas 100 MB
find /home -xdev -type f -name 'error_log' -size +100M -exec ls -lh {} \;
Opsi -x di du dan -xdev di find membuat pencarian tidak menyeberang ke filesystem lain. Ini penting kalau ada mount backup atau NFS di bawah direktori yang sama. Nama file error_log tanpa ekstensi itu khas setup tertentu. Di banyak server cPanel, PHP menulis error ke file error_log di direktori tempat script yang error berada. Akibatnya file ini bisa muncul di public_html, di folder wp-admin, atau di dalam folder plugin. Di VPS tanpa panel, lokasinya tergantung directive error_log di php.ini atau konfigurasi pool PHP-FPM. Kalau WP_DEBUG_LOG aktif, ada juga wp-content/debug.log yang bisa membengkak dengan cara yang sama.
Momen penyebabnya ketemu biasanya datang saat kita membuka beberapa ribu baris terakhir file itu. Jangan buka file gigabyte dengan editor. Pakai tail. Isinya cenderung repetitif, kurang lebih seperti ini (contoh format output, bukan log asli):
TEXT
[01-Jan-2026 00:00:01 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/user/public_html/wp-content/plugins/contoh-plugin/includes/ajax.php:5
[01-Jan-2026 00:00:01 UTC] PHP Deprecated:  Creation of dynamic property Contoh_Theme::$opsi is deprecated in /home/user/public_html/wp-content/themes/contoh-theme/functions.php:120
[01-Jan-2026 00:00:02 UTC] PHP Warning:  Undefined array key 'page' in /home/user/public_html/wp-content/themes/contoh-theme/header.php:33
Dua pola di atas menjelaskan kenapa bot bisa membuat log membengkak. Pola pertama terjadi saat bot memanggil file PHP plugin secara langsung. Banyak file di dalam folder plugin tidak dirancang untuk dibuka sendiri. File itu mengandalkan WordPress sudah dimuat lebih dulu. Kalau dipanggil langsung, fungsi seperti add_action() belum ada, lalu PHP melempar fatal error. Bot scanner suka melakukan ini untuk mengecek apakah plugin tertentu yang punya celah terpasang di situs. Pola kedua lebih halus. Request ke path yang tidak ada tetap diproses oleh index.php WordPress untuk menampilkan halaman 404. Kalau theme atau plugin menghasilkan notice atau deprecated warning di setiap page load, setiap 404 dari bot ikut menulis beberapa baris ke log. Di trafik normal ini tidak terasa. Dikalikan dengan ribuan request scanner per jam, ukurannya jadi besar. Jadi akar masalahnya adalah volume request yang dikalikan dengan error per request. Bot tidak perlu berhasil menembus apa pun untuk menghabiskan disk.
Error_log memberi tahu apa yang error. Access log memberi tahu siapa yang memicunya. Lokasi access log tergantung setup. Biasanya ada di /var/log/nginx/, /var/log/apache2/, /var/log/httpd/, atau direktori domlogs per domain di server cPanel. Ada satu jebakan saat disk 100% penuh. sort butuh ruang temporary untuk file besar, jadi perintah analisis bisa gagal di tengah jalan. Karena itu, ambil sampel ke partisi lain atau ke file kecil dulu, lalu analisis sampelnya. Perintah di bawah mengasumsikan access log berformat combined standar:
BASH
# baris error paling sering (timestamp dibuang supaya bisa dikelompokkan)
tail -n 200000 error_log | cut -d']' -f2- | sort | uniq -c | sort -rn | head -n 20

# IP dengan respons 404 terbanyak
awk '9 == 404 {print1}' access.log | sort | uniq -c | sort -rn | head -n 20

# path 404 yang paling sering diminta
awk '9 == 404 {print7}' access.log | sort | uniq -c | sort -rn | head -n 20

# request langsung ke file PHP plugin yang berujung 500
awk '7 ~ /wp-content\/plugins\/.*\.php/ &&9 == 500 {print 1,7}' access.log | sort | uniq -c | sort -rn | head -n 20

# user agent terbanyak
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -rn | head -n 10
Pola bot scanner biasanya mudah dikenali. Sekelompok kecil IP meminta puluhan path plugin berbeda yang sebagian besar tidak terpasang di situs kamu. Kadang ada juga path seperti .env, wp-config.php.bak, atau folder admin dari CMS lain. User agent-nya sering generik atau kosong. Kalau path di access log cocok dengan file yang muncul di error_log, rantai sebab-akibatnya sudah tertutup. Respons 200 di access log juga tidak otomatis berarti probe bot berhasil. Itu topik terpisah. Untuk insiden ini, yang penting adalah polanya.
Insting pertama biasanya langsung menjalankan rm error_log. Ini sering tidak membebaskan ruang. Kalau proses PHP atau web server masih memegang file itu dalam keadaan terbuka, file hilang dari daftar direktori, tapi blok datanya tetap terpakai sampai proses tersebut ditutup. Hasilnya df tetap penuh sementara du tidak menemukan apa-apa. Urutan yang lebih aman:
  1. Simpan sampel untuk analisis, misalnya tail -n 200000 error_log > /root/error_log.sample. Pastikan tujuannya ada di partisi yang masih punya ruang.
  2. Kosongkan isinya tanpa menghapus file dengan truncate -s 0 error_log. Perintah ini tidak bisa dibatalkan, isi lama hilang permanen, jadi pastikan sampel sudah tersimpan.
  3. Cek ulang dengan df -h bahwa ruang sudah kembali.
  4. Jalankan lagi service yang tumbang, biasanya database dulu, lalu PHP-FPM atau web server. Periksa status dan log masing-masing.
Setelah situs naik lagi, file akan langsung terisi ulang kalau sumbernya belum dihentikan. Ini cuma memberi napas. Untuk sementara, kamu bisa memblokir IP atau subnet terbanyak dari hasil analisis di firewall. Sadari bahwa scanner sering berganti IP, jadi langkah ini bersifat jangka pendek.
Perbaikan permanen menyerang dua sisi perkalian tadi, yaitu volume request dan error per request. Dari sisi volume, saring bot sebelum menyentuh PHP. Pilihannya bisa di level CDN/WAF, rate limit di web server, atau aturan yang menolak pola path yang jelas bukan milik situs kamu. Perbandingan blokir di edge dan di plugin dibahas di memilih blokir bot di Cloudflare atau plugin WordPress, dan logikanya sama untuk scanner. Menolak akses langsung ke file .php di dalam wp-content/plugins memang efektif, tapi ada plugin yang memang dipanggil langsung. Tes per situs dulu sebelum diterapkan. Dari sisi error, bersihkan sumber noise-nya. Update atau hapus plugin dan theme yang terus melempar notice dan deprecated. Plugin nonaktif yang filenya masih ada juga bisa jadi target pemanggilan langsung, jadi hapus kalau tidak dipakai. Di production, error_reporting bisa diatur supaya tidak mencatat E_DEPRECATED dan E_NOTICE, dan WP_DEBUG_LOG sebaiknya mati kalau tidak sedang debugging. Ini trade-off: log jadi lebih tenang, tapi peringatan dini soal kompatibilitas PHP ikut hilang. Kamu bisa mengimbanginya dengan staging yang lognya tetap lengkap. Terakhir, beri batas pada log itu sendiri. File error_log per situs sering tidak masuk rotasi bawaan sistem. Logrotate bisa menanganinya dengan directive seperti size, rotate, compress, dan copytruncate. copytruncate cocok untuk file yang terus dibuka proses lain. Cara memasangnya tergantung distro dan panel. Tambahkan juga alert disk di level tertentu, misalnya saat pemakaian melewati sekitar 80%, supaya kamu tahu lebih dulu sebelum database berhenti. Kalau disk VPS tiba-tiba penuh di server WordPress, cek file error_log dan debug.log dulu, ambil sampelnya, lalu kosongkan dengan truncate, bukan rm. Setelah itu, cari pasangan pola di access log, saring bot di depan PHP, matikan sumber noise di plugin atau theme, dan pastikan log punya rotasi serta alert. Tanpa langkah terakhir ini, kejadian yang sama biasanya terulang di gelombang scanner berikutnya.