654M di /var/log dan Task Bukti yang Diam-diam Bohong
Playbook mingguan bilang OK tapi /var/log bengkak 654M: arsip btmp rotasi, file aktif yang di-truncate, dan pipe df yang nggak pernah jalan.
Ringkasan
Disk /var/log bengkak diam-diam padahal playbook mingguan selalu lapor aman. Biang keroknya btmp, log login gagal yang numpuk gara-gara brute force SSH, fix-nya hapus arsip dan truncate file aktif biar sshd nggak perlu restart. Bonus: task bukti pakai modul command ternyata nggak memproses pipa, jadi harus diganti shell.
Playbook mingguan saya selalu lapor OK, tapi angka disk di dashboard saya terus merayap naik. Yang bikin jengkel, task bukti di playbook itu jalan tiap eksekusi: dia print hasil df ke log Ansible, dan isinya nggak pernah berubah berarti. Aman-aman aja. Sampai satu pagi saya iseng jalanin du -sh /var/log manual dan hasilnya 654M.
225M di luar journal, dan jujur saja bikin saya malu. Tebakan pertama saya journald. Terlalu gampang dipersalahkan, dan memang dia penyumbang terbesar: 429M. Tapi pas saya cek, vacuum playbook saya udah jalan dan cap-nya kepegang di 300M. Berarti ada 200M lebih yang bukan journal. Kandidat berikutnya cuma satu: btmp.1 sebesar 108M plus btmp aktif sebesar 47M.
File Log yang Dibikin Gemuk sama Brute Force
Untuk yang jarang nyentuh: wtmp itu file yang nyatat semua login dan logout. Dia dipelihara sama login, init, dan beberapa varian getty, dan man page-nya bilang nggak ada satu pun program itu yang bikin filenya sendiri, jadi kalau file-nya dihapus, pencatatan mati [4]. last baca file itu buat nampilin riwayat login, paling baru di atas [7]. btmp itu sepupunya yang khusus nampung login gagal, dan server email yang ke-expose SSH ke internet tujuannya jelas: tiap bot yang nyoba password nyimpen jejaknya di situ, bertahun-tahun, tanpa pernah dibersihin.
Jadi arah perbaikannya dua lapis. Arsip rotasi boleh dibuang. File aktif jangan dihapus, cukup dikosongin.
Jebakan Kecil di Task Bukti
Sambil nyusun task pembersihan, saya sadar ada yang aneh di playbook lama. Task bukti saya nulis begini:
- name: Before/after evidence
ansible.builtin.command: df -h / | tail -1
Ternyata modul command itu nggak memproses perintah lewat shell, jadi karakter pipa, redirect, dan kawan-kawannya cuma dianggap argumen mati [5]. Selama ini yang jalan cuma df -h / utuh, tabel panjang tanpa filter, dan saya yang nggak pernah curiga karena output-nya memang muncul. Dokumentasinya sendiri nyaranin pindah ke modul shell kalo butuh karakter kayak gitu, dan tetap pakai command kalo nggak, karena lebih aman [5]. Fix-nya satu kata: ganti command jadi shell.
Yang bikin saya betah sama pola truncate: dia nggakpihak sama siapa pun. logrotate jalan di belakang, sshd nggak perlu tahu, dan playbook cuma jadi jaring pengaman kalau dua-duanya sempat bolong. Angka 50M itu sendiri juga sengaja longgar; bukan target, cuma batas "udah kelewatan" sebelum playbook turun tangan.
Satu hal yang baru saya sadar setelah kejadian: task bukti yang rusak itu bahaya dia justru karena kelihatan sehat. Output df selalu muncul di log, jadi saya punya ilusi bahwa playbook "ngecek disk" tiap minggu. Padahal yang saya butuhkan cuma satu baris terakhir, dan baris itu nggak pernah ada. Monitoring yang ngasih data lebih dari yang diminta kadang lebih susah dilawan daripada yang nggak ngasih apa-apa.
Truncate, Bukan rm
Buat file aktif di atas 50M, playbook sekarang jalanin truncate -s 0. Perintah ini motong file ke ukuran yang kita minta; datanya hilang, tapi file-nya tetap ada, termasuk inode dan permission-nya [6]. Itu poin pentingnya: sshd yang lagi megang file descriptor btmp nggak sadar ada yang berubah, dia terus nulis kayak biasa, nggak perlu restart. Kalo file-nya dihapus, proses yang udah megang descriptor lama tetap nulis ke file yang udah nggak kelihatan, sementara pencatatan barunya nggak kebikin.
Task di ansible/playbooks/mitigate-disk.yml jadi tiga langkah: find dengan regex buat nampung arsip btmp/wtmp yang udah dirotasi, loop file state=absent buat nghapusnya, dan satu task shell yang nyari file aktif di atas 50M buat di-truncate. Ditambah dua task du -sh /var/log sebelum-sesudah buat bukti.
Hasil di server yang bermasalah: 654M turun ke 418M, 112M kebebas, dan eksekusi kedua lapor changed=0. Angka kedua itu yang paling saya hargai, karena artinya playbook-nya idempoten. Sisa pekerjaannya satu: guard logrotate biar btmp nggak lagi kesempatan bengkak diam-diam. Itu jadi commit lanjutan, dan playbook mingguan akhirnya balik jadi alat yang jujur.
Sumber
1. utmp(5) - login records, Linux man-pages
2. ansible.builtin.command module, Ansible docs
3. truncate(1), Linux man-pages
Sumber:
[4] https://man7.org/linux/man-pages/man5/wtmp.5.html
[5] https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html