Password database yang tertulis di crontab adalah bom waktu — sekali file bocor, semua aset terbuka. Episode ini mengajarkan menyimpan secrets di env file ber-permission 600 atau secret manager seperti Vault, plus disiplin scripting: set -euo pipefail, path absolut, dan validasi input.

Di episode 13 kita membatasi siapa yang boleh menjadwalkan dan dengan privilege apa. Sekarang kita bahas isi dari job itu sendiri: script dan secrets-nya.
Skenario yang terlalu umum: crontab berisi pg_dump -U root -p Sekret123. Sekarang bayangkan crontab itu ter-backup ke repository, dibagikan di pastebin, atau dilihat user yang seharusnya tidak — password bocor, dan karena job dijalankan berkala, kebocoran tidak terdeteksi sampai terlambat. Episode ini menutup celah itu.
/var/spool/cron/crontabs/ — beberapa tool backup ikut menyalinnya.Aturan emasnya: crontab hanya berisi jadwal; secrets hidup di tempat lain.
Simpan secrets dalam file terpisah yang hanya bisa dibaca user pemilik:
RESTIC_PASSWORD=very-strong-secret
PGPASSWORD=db-secret
DB_HOST=localhostchmod 600 /home/deploy/.backup.env
chown deploy:deploy /home/deploy/.backup.envMuat dari script:
#!/bin/bash
set -a
source /home/deploy/.backup.env
set +a
pg_dump -h "$DB_HOST" -U backup_user -Fc mydb > /backup/mydb.dumpset -a mengekspor semua variabel yang di-source sehingga bisa diwariskan ke proses anak (seperti pg_dump).
Warning
chmod 600 hanya melindungi dari user lain — tidak melindungi dari root, dan tidak melindungi dari proses yang berjalan sebagai user yang sama. Ini adalah kontrol dasar, bukan pengganti secret manager. Kombinasikan dengan user khusus (episode 13) dan pertimbangkan Vault untuk secrets yang lebih sensitif.
Untuk organisasi yang lebih besar, secret manager seperti HashiCorp Vault atau OpenBao adalah jawabannya:
#!/bin/bash
export PGPASSWORD=$(vault kv get -field=password secret/db/backup)
pg_dump -h localhost -U backup_user -Fc mydb > /backup/mydb.dumpKeunggulan: rotasi terpusat, audit log siapa mengakses secret apa, dan tanpa file teks yang menumpuk di disk. Kekurangan: butuh token Vault yang juga harus dijaga dan infrastruktur tambahan.
Tiga opsi bash yang mengubah script dari "mungkin gagal diam-diam" menjadi "gagal dengan jelas":
#!/bin/bash
set -euo pipefail-e — keluar segera saat perintah mengembalikan exit code non-0.-u — error saat memakai variabel yang belum di-set (menangkap typo).-o pipefail — pipeline dianggap gagal jika salah satu tahapnya gagal, bukan hanya tahap terakhir.Tanpa -o pipefail, pg_dump | gzip yang pg_dump-nya gagal tetap dianggap sukses karena gzip mengembalikan 0.
Ingat pelajaran episode 6: jangan mengandalkan PATH. Gunakan path absolut atau bangun PATH di dalam script:
#!/bin/bash
set -euo pipefail
export PATH=/usr/local/bin:/usr/bin:/bin
LOGFILE=/var/log/backup.log
exec > >(tee -a "$LOGFILE") 2>&1Script yang menerima argumen harus memvalidasinya sebelum bekerja:
#!/bin/bash
set -euo pipefail
TARGET="${1:?Argumen TARGET wajib diisi}"
if [[ ! -d "$TARGET" ]]; then
echo "ERROR: $TARGET bukan direktori" >&2
exit 1
fi${1:?pesan} langsung keluar dengan pesan jika argumen kosong — mencegah script bekerja dengan nilai yang salah.
Note
Kombinasi set -euo pipefail + validasi + path absolut tidak membuat script kebal error — tetapi mengubah error tersembunyi menjadi error terlihat, yang bisa di-log dan di-alert (episode 12). Visibilitas adalah prasyarat keandalan.
| Praktik | Mencegah | Alat |
|---|---|---|
| No hardcode secrets | Kebocoran kredensial | Env file 600 / Vault |
chmod 600 | Pembacaan oleh user lain | File permission |
set -euo pipefail | Kegagalan tersembunyi | Bash options |
| Path absolut | command not found | Script |
| Validasi input | Kerusakan karena argumen salah | Guard clauses |
Inti yang harus dibawa pulang:
set -euo pipefail membuat kegagalan menjadi terlihat.Di episode 15 selanjutnya kita akan membahas cron di container dan Kubernetes CronJob — kenapa crond di dalam container adalah anti-pattern, bagaimana menggantinya dengan entrypoint loop atau K8s CronJob, dan anatomi manifest batch/v1 dengan schedule, concurrencyPolicy, dan TTL!