Rotasi Log #
File log Nginx yang kita aktifkan akan terus tumbuh seiring dengan waktu dan volume lalu lintas (traffic) yang masuk ke server kita. Pada server produksi dengan lalu lintas sedang hingga padat, berkas access log dapat dengan mudah mengumpulkan data hingga bergiga-giga bita dalam hitungan minggu atau bahkan hari. Jika dibiarkan tanpa pengelolaan, berkas log yang terus membesar ini akan menghabiskan seluruh kapasitas penyimpanan disk server kita, menyebabkan kegagalan sistem secara keseluruhan, serta memperlambat kinerja utilitas pembaca log.
Untuk mengatasi tantangan ini, kita menerapkan praktik Rotasi Log (log rotation). Rotasi log adalah proses otomatisasi untuk memotong file log aktif secara berkala, mengompres file log lama ke dalam format arsip guna menghemat ruang penyimpanan, membatasi jumlah file arsip yang disimpan (retensi), dan secara otomatis membuat file log baru yang bersih. Di artikel ini, kita akan mempelajari mekanisme internal bagaimana Nginx mengunci file log, bagaimana signal USR1 digunakan untuk membuka kembali berkas log, membedah berkas konfigurasi logrotate standar di Linux, serta melakukan pengujian dan monitoring penyimpanan log secara mandiri.
Mengapa Kita Membutuhkan Rotasi Log? #
Menumpuk seluruh data lalu lintas ke dalam satu berkas tunggal yang sangat besar (misalnya file access.log berukuran 50 GB) menimbulkan beberapa masalah operasional yang serius bagi kita:
- Risiko Kehabisan Disk (Disk Exhaustion): Ini adalah bahaya paling nyata. Jika partisi disk tempat log disimpan terisi 100%, sistem operasi Linux tidak akan bisa menulis data baru. Layanan database akan berhenti, sistem caching akan macet, dan Nginx sendiri mungkin akan gagal memproses request baru.
- Penurunan Performa Utilitas: Mencoba membaca, mencari kata kunci (menggunakan
grepatauawk), atau menganalisis file log berukuran puluhan gigabyte akan memakan waktu yang sangat lama dan mengonsumsi memori RAM server dalam jumlah besar. - Kepatuhan Hukum (Compliance): Regulasi perlindungan data sering kali membatasi durasi penyimpanan log aktivitas pengguna (misalnya, hanya boleh disimpan selama 30 hari atau 90 hari). Dengan rotasi log, kita dapat secara otomatis menghapus berkas log lama yang telah melewati batas retensi tersebut untuk mematuhi aturan hukum.
Cara Kerja Nginx Menangani Berkas Log #
Ada satu konsep teknis krusial tentang sistem operasi Linux dan Nginx yang wajib dipahami oleh setiap administrator sistem: Nginx memegang pengenal berkas terbuka (file descriptor) pada file log secara terus-menerus.
Ketika proses worker Nginx menulis baris log ke /var/log/nginx/access.log, ia tidak mencari file berdasarkan namanya setiap kali menulis. Nginx menggunakan nomor file descriptor yang diperoleh saat pertama kali membuka file tersebut.
Hal ini memicu perilaku berikut:
- Jika kita mengganti nama (rename) file
access.logmenjadiaccess.log.1, Nginx tetap akan menulis log ke fileaccess.log.1tersebut. Nginx tidak akan otomatis membuat fileaccess.logyang baru karena file descriptor yang dipegangnya masih mengarah ke inode file yang sama di disk. - Bahkan jika kita menghapus file
access.logsecara langsung menggunakan perintahrm, Nginx tetap akan menulis ke file descriptor tersebut. Ruang disk tidak akan dibebaskan oleh sistem operasi hingga kita memberitahu Nginx untuk menutup file descriptor lama.
Signal USR1 (nginx -s reopen)
#
Untuk memberitahu Nginx agar melepas file descriptor lama dan membuka file log baru yang bersih, kita harus mengirimkan signal sistem bernama USR1 ke proses master Nginx.
Setelah menerima signal USR1, master process Nginx akan memerintahkan semua worker process untuk:
- Menutup berkas log yang saat ini terbuka.
- Membuka kembali berkas log menggunakan nama file asli yang tertulis di konfigurasi Nginx (yang akan mendeteksi bahwa file tersebut kosong atau baru dibuat).
- Membuat berkas log baru dengan hak akses yang sesuai jika file tersebut belum ada di disk.
Berikut adalah alur sequence diagram proses rotasi log di Nginx:
sequenceDiagram
autonumber
participant LR as Logrotate Agent
participant OS as OS File System
participant NX as Nginx Master Process
LR->>OS: Rename access.log menjadi access.log.1
Note over NX: Nginx tetap menulis log ke<br/>access.log.1 via file descriptor
LR->>OS: Buat file access.log kosong baru (opsional)
LR->>NX: Kirim signal USR1 (nginx -s reopen)
NX->>OS: Tutup file descriptor access.log.1
NX->>OS: Buka file descriptor baru ke access.log
Note over NX: Nginx mulai menulis log ke<br/>file access.log yang baru
LR->>OS: Kompres access.log.1 menjadi access.log.1.gzPerintah manual untuk mengirimkan signal USR1 ini adalah:
# Metode 1: Menggunakan perintah nginx bawaan
sudo nginx -s reopen
# Metode 2: Mengirimkan signal kill langsung ke PID master Nginx
sudo kill -USR1 $(cat /var/run/nginx.pid)
Konfigurasi Utilitas logrotate Standar
#
Di sebagian besar distribusi Linux (seperti Ubuntu, Debian, Rocky Linux, CentOS), kita tidak perlu membuat skrip rotasi log sendiri. Sistem operasi telah menyertakan utilitas standar bernama logrotate yang berjalan secara berkala (biasanya sebagai cron job harian atau systemd timer).
Saat kita menginstal Nginx melalui package manager (apt atau dnf), installer akan otomatis menaruh berkas konfigurasi logrotate Nginx di /etc/logrotate.d/nginx.
Mari kita membedah isi konfigurasi /etc/logrotate.d/nginx standar untuk memahami fungsionalitas masing-masing parameter:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
Penjelasan Parameter Baris Demi Baris #
/var/log/nginx/*.log: Menentukan target berkas log yang akan diproses oleh aturan di dalam kurung kurawal. Dalam hal ini, semua file berakhiran.logdi dalam direktori/var/log/nginx/.daily: Menentukan frekuensi rotasi. Berkas log akan dirotasi setiap hari. Pilihan lainnya adalahweekly(mingguan),monthly(bulanan), atauyearly(tahunan).missingok: Jika karena suatu alasan file log tidak ditemukan (misalnya kita menghapusnya secara manual), logrotate akan mengabaikannya dan melanjutkan proses tanpa memicu pesan error ke sistem.rotate 14: Menentukan retensi log. Kita hanya menyimpan maksimal 14 berkas log lama yang telah dirotasi. Pada hari ke-15, file log tertua (access.log.14.gz) akan dihapus secara permanen untuk menghemat ruang disk.compress: Mengompres berkas log lama yang dirotasi menggunakan gzip untuk menghemat ruang penyimpanan hingga 80-90%.delaycompress: Menunda proses kompresi satu siklus rotasi. File log yang baru saja dirotasi pada hari ini (access.log.1) tidak akan langsung dikompres menjadi.gz. File tersebut baru akan dikompres pada rotasi hari berikutnya (menjadiaccess.log.2.gz). Ini sangat penting karena memberi waktu bagi worker process Nginx untuk benar-benar menyelesaikan penulisan dan menutup file descriptor lama mereka setelah menerima signal reopen.notifempty: Jangan melakukan rotasi jika berkas log aktif dalam kondisi kosong (tidak ada lalu lintas data). Ini menghemat ruang disk dan mencegah pembuatan file arsip kosong yang tidak berguna.create 0640 www-data adm: Setelah me-rename file log lama, logrotate akan langsung membuat file log kosong yang baru dengan izin akses0640(pemilik bisa baca/tulis, grup bisa baca, orang lain tidak bisa mengakses sama sekali), dengan kepemilikan userwww-datadan grupadm.sharedscripts: Menginstruksikan logrotate untuk menjalankan skrip di dalam blokpostrotatehanya satu kali setelah semua file log selesai diproses, bukan satu kali untuk setiap file log yang ditemukan. Ini mencegah server Nginx di-reload berulang kali jika ada banyak file log virtual host yang dirotasi bersamaan.postrotate ... endscript: Blok perintah shell yang akan dieksekusi setelah proses rotasi selesai. Di sinilah kita menaruh perintahkill -USR1untuk memerintahkan Nginx membuka kembali berkas log baru yang kosong.
Kustomisasi Aturan Rotasi Log untuk Virtual Host Spesifik #
Konfigurasi bawaan logrotate Nginx memperlakukan semua file log secara seragam. Namun di lingkungan produksi, kita mungkin ingin menyimpan log dari virtual host tertentu lebih lama (karena alasan compliance transaksi bisnis) dibandingkan log aset statik atau log subdomain pengujian yang kurang penting.
Kita dapat mengaturnya dengan memisahkan blok target file log di konfigurasi /etc/logrotate.d/nginx:
# Aturan 1: Log Utama API (Disimpan 90 hari untuk compliance audit)
/var/log/nginx/api.unisbadri.com-*.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
# Aturan 2: Log Aset Statis (Cukup simpan 3 hari karena isinya hanya request file CSS/JS/Gambar)
/var/log/nginx/static-assets-*.log {
daily
rotate 3
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
Dengan konfigurasi ini, kita secara cerdas mengoptimalkan penggunaan kapasitas penyimpanan disk server kita dengan tidak menyimpan data log yang tidak bernilai tinggi terlalu lama.
Pengujian dan Eksekusi Rotasi Log Secara Manual #
Setelah mengubah konfigurasi logrotate Nginx, kita harus mengujinya untuk memastikan tidak ada kesalahan ketik (syntax error) yang dapat menggagalkan proses rotasi harian otomatis.
1. Uji Coba Simulasi (Dry Run) #
Kita dapat menjalankan simulasi rotasi log tanpa benar-benar mengubah file apa pun di disk dengan menggunakan parameter --debug:
sudo logrotate --debug /etc/logrotate.d/nginx
Perintah ini akan menampilkan log langkah demi langkah mengenai apa yang akan dilakukan oleh logrotate, file apa saja yang akan diganti namanya, serta perintah postrotate apa yang akan dijalankan.
2. Memaksa Rotasi Langsung (Force Rotate) #
Jika kapasitas disk kita sudah hampir penuh dan kita ingin segera memicu rotasi log saat ini juga tanpa menunggu jadwal otomatis sistem:
sudo logrotate --force /etc/logrotate.d/nginx
Perintah ini akan memaksa logrotate untuk memutar seluruh file log Nginx, membuat file baru, mengompres file lama, dan mereload Nginx.
3. Memantau Status Rotasi Terakhir #
Utilitas logrotate menyimpan log tanggal eksekusi terakhir dari setiap aturan konfigurasi di dalam file status:
sudo cat /var/lib/logrotate/status | grep nginx
Rotasi Log pada Nginx di dalam Docker Container #
Ketika kita menjalankan Nginx di dalam kontainer Docker, pendekatan rotasi log tradisional menggunakan logrotate di tingkat OS host tidak dapat diterapkan secara langsung. Secara default, citra (image) resmi Docker Nginx mengonfigurasi access log dan error log untuk dialihkan ke /dev/stdout (standard output) dan /dev/stderr (standard error):
# Konfigurasi default di dalam Docker image Nginx
access_log /dev/stdout;
error_log /dev/stderr;
Tujuan dari pengalihan ini adalah agar semua log Nginx dapat ditangkap langsung oleh Docker Daemon dan dikonsumsi melalui perintah docker logs <container_id>.
Dalam arsitektur Docker ini, rotasi log tidak dilakukan di dalam Nginx, melainkan didelegasikan ke tingkat Docker daemon menggunakan logging driver. Jika kita tidak membatasinya, berkas log JSON Docker di server host (/var/lib/docker/containers/*/*-json.log) akan membesar tanpa batas.
Konfigurasi Rotasi Log Docker Daemon #
Kita harus mengonfigurasi batas ukuran log Docker secara global pada file /etc/docker/daemon.json di server host kita:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
max-size: "10m": Docker akan merotasi log kontainer ketika ukuran berkas log mencapai 10 Megabyte.max-file: "3": Docker hanya akan menyimpan maksimal 3 file log lama per kontainer.
Setelah berkas dikonfigurasi, kita harus merestart layanan Docker:
sudo systemctl restart docker
Jika kita tetap ingin menulis log ke file lokal di dalam Docker kontainer (misalnya karena kita butuh file log JSON terpisah untuk Promtail/Filebeat), kita harus me-mount direktori log tersebut ke server host menggunakan Docker volume, lalu mengonfigurasi logrotate di tingkat server host untuk merotasi file tersebut dan mengirimkan signal USR1 ke kontainer menggunakan perintah:
# Perintah postrotate khusus untuk kontainer Docker Nginx
docker exec -it <container_name_or_id> nginx -s reopen
Rotasi Log Manual Menggunakan Skrip Lightweight Cron #
Pada sistem minimalis yang tidak terinstal utilitas logrotate (seperti pada beberapa instalasi Docker Alpine minimalis atau server IoT), kita dapat menulis skrip shell sederhana kita sendiri untuk melakukan rotasi log secara aman, lalu menjadwalkannya menggunakan cron bawaan.
Berikut adalah contoh skrip shell (/usr/local/bin/rotasi-nginx.sh) yang aman:
#!/bin/sh
# Tentukan konfigurasi path
LOG_DIR="/var/log/nginx"
PID_FILE="/var/run/nginx.pid"
BACKUP_DATE=$(date +"%Y%m%d_%H%M%S")
# 1. Masuk ke direktori log
cd "$LOG_DIR" || exit 1
# 2. Rename file aktif saat ini
for log_file in *.log; do
# Lewati jika tidak ada file log aktif
[ -f "$log_file" ] || continue
# Ganti nama file aktif menjadi file cadangan bertanggal
mv "$log_file" "${log_file}.${BACKUP_DATE}"
done
# 3. Kirim signal USR1 ke Nginx untuk membuat file log baru yang bersih
if [ -f "$PID_FILE" ]; then
kill -USR1 "$(cat "$PID_FILE")"
else
echo "Peringatan: PID Nginx tidak ditemukan, gagal reopen log."
fi
# 4. Beri jeda 2 detik bagi worker process Nginx untuk menutup FD lama
sleep 2
# 5. Kompres file log cadangan yang baru dibuat
for backup_file in *.log.[0-9]*; do
[ -f "$backup_file" ] || continue
gzip "$backup_file"
done
# 6. Hapus log cadangan yang lebih tua dari 14 hari
find "$LOG_DIR" -name "*.log.*.gz" -mtime +14 -exec rm -f {} \;
Setelah membuat skrip tersebut, jangan lupa untuk memberikan izin eksekusi:
sudo chmod +x /usr/local/bin/rotasi-nginx.sh
Kemudian, kita daftarkan skrip tersebut di crontab root (sudo crontab -e) agar berjalan setiap malam pukul 23:59:
59 23 * * * /usr/local/bin/rotasi-nginx.sh >/dev/null 2>&1
Pemantauan Kapasitas Penyimpanan Disk Log #
Sebagai bagian dari pemeliharaan rutin, kita harus selalu memantau konsumsi ruang disk yang digunakan oleh file log Nginx kita.
1. Memeriksa Ukuran File Log #
Kita dapat memeriksa file log mana saja yang memakan kapasitas penyimpanan terbesar menggunakan perintah du (disk usage):
# Tampilkan ukuran masing-masing file log di direktori Nginx
sudo du -sh /var/log/nginx/* | sort -h
2. Mencari File Log Berukuran Besar yang Melebihi Batas #
Jika kita ingin memindai apakah ada berkas log yang tumbuh terlalu cepat melebihi 1 GB:
sudo find /var/log/nginx/ -type f -name "*.log" -size +1G
3. Menghapus Log Lama Secara Aman #
Jangan pernah menghapus file log aktif menggunakan perintah rm tanpa mereload Nginx. Cara paling aman untuk membersihkan isi file log aktif secara instan tanpa mengganggu Nginx adalah dengan mengosongkan isinya (truncating):
# Kosongkan berkas log aktif menjadi 0 bita secara aman
sudo truncate -s 0 /var/log/nginx/access.log
Perintah truncate akan menghapus seluruh isi data di dalam berkas namun tetap mempertahankan file descriptor dan inode berkas, sehingga Nginx dapat langsung melanjutkan penulisan tanpa mengalami error.
Ringkasan dan Praktik Terbaik #
- Selalu Gunakan delaycompress: Pastikan parameter
delaycompressselalu diaktifkan bersamacompressagar Nginx memiliki cukup waktu untuk menutup file descriptor lama sebelum kompresi gzip dilakukan.- Gunakan sharedscripts: Gunakan parameter
sharedscriptsagar skrip pemanggilan signalUSR1ke Nginx hanya dieksekusi satu kali saja setelah semua file log selesai diproses.- Kosongkan Log Secara Aman: Jika harus membersihkan log aktif secara darurat, gunakan perintah
truncate -s 0 file.logalih-alih menggunakan perintahrmatauecho "" > file.log.- Pisahkan Retensi Log: Bedakan durasi penyimpanan (retensi) log API sensitif (simpan lebih lama) dengan log aset statik (simpan lebih singkat) untuk menghemat ruang disk.
- Lakukan Dry Run Setelah Mengedit: Selalu jalankan
logrotate --debug /etc/logrotate.d/nginxsetelah mengubah aturan rotasi untuk mendeteksi kesalahan konfigurasi sejak awal.
← Sebelumnya: Format Log Kustom Berikutnya: Worker Process →