Lindungi password, API key, dan kredensial dengan Ansible Vault. Pelajari ansible-vault encrypt, view, edit, decrypt, encrypt_string, --ask-vault-pass, vault-password-file, hingga multiple vault IDs untuk memisahkan environment.

Setelah di episode 13 sebelumnya kita membahas Ansible Collections dan Ansible Galaxy untuk memperkaya ekosistem automasi, pada episode kali ini kita akan membahas salah satu topik paling kritis di dunia infrastruktur modern: keamanan rahasia (secret management) menggunakan Ansible Vault.
Coba bayangkan skenario nyata ini: sebuah tim DevOps mengelola repository Ansible di GitHub. Di dalamnya ada file group_vars/production.yml yang berisi mysql_root_password, api_key_payment_gateway, dan ssh_private_key. Suatu hari, salah satu anggota tim melakukan force-push ke cabang yang salah, atau repository privat diubah menjadi publik karena kesalahan pengaturan. Secepat itu, seluruh kredensial produksi terpapar ke publik. Serangan berikutnya bukan lagi soal "apakah", tapi "kapan": server di-scan, database diretas, dan tagihan cloud membengkak.
Ini bukan cerita fiksi. Kebocoran secret di Git adalah salah satu penyebab insiden keamanan paling umum di industri, dan biaya perbaikannya sangat mahal. Di episode ini kita akan membahas mengapa menyimpan rahasia dalam plaintext di Git adalah praktik yang berbahaya, bagaimana Ansible Vault melindunginya dengan enkripsi AES-256, penggunaan lengkap CLI ansible-vault, menjalankan playbook terenkripsi dengan --ask-vault-pass dan --vault-password-file, multiple vault IDs untuk memisahkan environment, serta best practices menjaga keamanan keseluruhan.
Sebelum masuk ke solusi, mari kita pahami betul mengapa plaintext secret di Git adalah masalah besar. Ada beberapa alasan fundamental:
git log -p. Menghapus file saja tidak cukup.Ansible Vault hadir untuk memecahkan masalah ini. Ansible Vault adalah fitur bawaan Ansible yang mengenkripsi file atau variabel menggunakan algoritma AES-256 (dengan dukungan autentikasi integrity). File terenkripsi tetap bisa di-commit ke Git dengan aman, karena isinya hanya bisa dibaca dengan vault password yang tidak pernah disimpan di repository.
Warning
Ansible Vault mengenkripsi isi file, bukan nama file, metadata, atau struktur directory. Nama file seperti group_vars/production.yml tetap terlihat jelas di Git. Jika nama file itu sendiri sensitif (misalnya aws-root-credentials.yml), pertimbangkan memberi nama yang netral atau menggunakan vault ID yang berbeda.
ansible-vaultCLI ansible-vault menyediakan serangkaian sub-command untuk mengelola enkripsi. Berikut ringkasannya:
| Sub-command | Fungsi |
|---|---|
ansible-vault create <file> | Membuat file baru sekaligus terenkripsi |
ansible-vault encrypt <file> | Mengenkripsi file yang sudah ada |
ansible-vault view <file> | Melihat isi file terenkripsi (decrypt to stdout) |
ansible-vault edit <file> | Mengedit file terenkripsi (dibuka di editor) |
ansible-vault decrypt <file> | Mendekripsi file kembali ke plaintext |
ansible-vault encrypt_string | Mengenkripsi string variabel tertentu |
ansible-vault rekey <file> | Mengganti password vault pada file terenkripsi |
Semua sub-command yang mengubah data akan meminta vault password (interaktif) atau membaca dari opsi --vault-password-file/--vault-id jika diberikan.
ansible-vault encryptMari kita mulai dari skenario yang paling umum: kita punya file variabel berisi kredensial database. Pertama, kita buat file plaintext-nya:
---
db_user: "admin_prod"
db_password: "B4ny4kRah4sia-Super#2026"
db_name: "ecommerce"
api_key_payment: "sk_live_8f3k..."Sekarang enkripsi file tersebut dengan ansible-vault encrypt:
ansible-vault encrypt group_vars/production.ymlAnsible akan meminta password vault dua kali (untuk konfirmasi):
New Vault password:
Confirm New Vault password:
Encryption successfulBegitu selesai, isi file berubah menjadi blok terenkripsi:
$ANSIBLE_VAULT;1.1;AES256
39633631623263343838653437356232333034383432316666343663383933336638363366393233
3233323935343138613764373831333566363835646331320a343031633563353965663735316465
36376537386364346636643762303263333538356563616161623665656566653337646234643162
6332353233306333350a616363326562366438346137643134373737363764326562316465666664
61386461653438383437363535636433393362613136356234383932653361383534383631316662
32656664663761353434343337343339346334343133343832666536663164383638393663343339
62393165316137613330643761643262646633666465383930376432666334656438393735626562
6332Note
Format header $ANSIBLE_VAULT;1.1;AES256 menandakan versi format, dan 1.1 merujuk pada cipher text. Secara default Ansible Vault menggunakan algoritma AES-256 dalam mode CBC dengan HMAC-SHA256 untuk integritas. Header ini juga menjadi penanda bahwa Ansible akan otomatis mendekripsi file ini saat playbook dijalankan, selama vault password tersedia.
Setelah file terenkripsi, kita bisa dengan aman melakukan git add dan git commit. Isi yang terlihat di Git hanyalah cipher text yang tidak berguna tanpa password.
Karena file sudah terenkripsi, kalian tidak bisa langsung cat isinya. Gunakan ansible-vault view untuk melihat isi file tanpa menyimpannya sebagai plaintext:
ansible-vault view group_vars/production.ymlSetelah memasukkan password, isi plaintext ditampilkan ke terminal:
Vault password:
---
db_user: "admin_prod"
db_password: "B4ny4kRah4sia-Super#2026"
db_name: "ecommerce"
api_key_payment: "sk_live_8f3k..."Untuk mengubah isi, gunakan ansible-vault edit. File dibuka di editor default (biasanya $EDITOR atau vi) dalam bentuk plaintext sementara, lalu dienkripsi ulang saat disimpan:
ansible-vault edit group_vars/production.ymlJika kalian perlu mengembalikan file ke plaintext (misalnya untuk migrasi atau audit), gunakan ansible-vault decrypt:
ansible-vault decrypt group_vars/production.ymlCaution
ansible-vault decrypt sangat berbahaya jika dilakukan tanpa sadar: file menjadi plaintext di disk dan bisa ter-commit jika kalian lupa. Best practice: hindari decrypt kecuali benar-benar diperlukan, dan jika harus, segera lakukan git status untuk memastikan file plaintext tidak ikut ter-commit. Banyak tim bahkan melarang penggunaan decrypt di repositori bersama.
ansible-vault encrypt_stringTerkadang kita tidak ingin mengenkripsi seluruh file, hanya satu variabel saja — misalnya password di dalam playbook atau di --extra-vars. Sub-command encrypt_string menangani kasus ini:
ansible-vault encrypt_string "B4ny4kRah4sia-Super#2026" --name db_passwordOutput yang dihasilkan adalah blok YAML yang siap tempel ke playbook atau file vars:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
39393831393433613630323537363538366232623238316131633064303938323532336466623239
3937656165353134666565636364656338316235613337340a626564376562646139633564653038
33343839363366333962366330366636343266376465626364616539383863656562626532396261
3734346462373538640a626365336338313436343630626565323963643861626561333364386133
35656233656234376663333362653862363234356232396435346162386432643232316539393334
36613662633232613732396236313536646463396362663136336632373231323437366362623866
31646232336438346564343737323738333837306265353036343765663732663962623330393163
34346363616330613833623736666239353633373233663464346137316265373661663634376565
66366236663363663762393661666533626633343362333132666363346130346265376231376162
65336165666234663230336539336333313761666233663330366135303238353638643238393332
62343966663537623437623264393932353661613962383264653061303434343762303437643966
3934Tip
Gunakan opsi --vault-id <label>@prompt pada encrypt_string untuk menandai string dengan vault ID tertentu. Hasilnya akan menampilkan <label> di dalam header blok vault ($ANSIBLE_VAULT;1.2;AES256;<label>), sehingga ketika mendekripsi, Ansible langsung tahu password mana yang harus dipakai. Ini sangat membantu saat bermain dengan multiple vault IDs.
Setelah variabel terenkripsi (baik via file atau encrypt_string), pemakaiannya di playbook sama sekali tidak berubah — Ansible mendekripsi secara otomatis saat runtime selama password vault tersedia. Contoh playbook yang memakai group_vars/production.yml terenkripsi:
---
- name: Konfigurasi database produksi
hosts: dbservers
become: true
tasks:
- name: Buat database baru
community.mysql.mysql_db:
name: "{{ db_name }}"
state: present
login_user: "{{ db_user }}"
login_password: "{{ db_password }}"Perhatikan: playbook tidak berubah sama sekali dibandingkan bila group_vars/production.yml masih plaintext. Yang membedakan hanyalah cara menjalankan playbook: kita wajib menyediakan vault password, kalau tidak Ansible akan gagal dengan error "Attempting to decrypt but no vault secrets found".
Ada dua cara utama menyediakan vault password saat menjalankan playbook: interaktif dan non-interaktif.
--ask-vault-passPaling sederhana untuk penggunaan lokal. Ansible akan meminta password vault secara interaktif setiap kali playbook dijalankan:
ansible-playbook -i inventory.yml playbook-deploy-db.yml --ask-vault-passOutputnya:
Vault password:
PLAY [Konfigurasi database produksi] *******************************************
TASK [Gathering Facts] ********************************************************
ok: [db01]Keunggulannya jelas: password tidak pernah tersimpan di disk maupun di history shell. Kekurangannya: tidak cocok untuk otomatisasi (CI/CD), karena butuh input manusia.
--vault-password-fileUntuk otomatisasi, password vault disimpan dalam file lokal yang tidak di-commit ke Git, lalu dirujuk lewat flag --vault-password-file:
echo "my-strong-vault-password" > ~/.vault_pass.txt
chmod 600 ~/.vault_pass.txtansible-playbook -i inventory.yml playbook-deploy-db.yml \
--vault-password-file ~/.vault_pass.txtImportant
Aturan wajib: jangan pernah meng-commit file password vault. Selalu tambahkan ke .gitignore dan pastikan permission-nya 600 (hanya owner yang bisa baca). File password vault adalah key dari seluruh enkripsi kalian; jika bocor, enkripsi menjadi tidak ada artinya. Best practice-nya, simpan file ini di lokasi aman terpisah (misalnya di secret manager CI/CD) dan inject ke pipeline saat runtime.
Berikut perbandingan kedua opsi dalam satu pandangan:
ansible-playbook -i inventory.yml playbook.yml \
--ask-vault-pass
# Kelebihan: password tidak tersimpan di disk
# Kekurangan: butuh input manusia, tidak cocok CI/CDSekarang kita masuk ke fitur yang sangat penting di produksi: vault IDs. Dengan vault ID, kalian bisa mengenkripsi file yang berbeda dengan password yang berbeda, masing-masing diberi label. Ini memungkinkan pemisahan secret untuk development, staging, dan production — sehingga seorang engineer hanya bisa membaca secret environment tertentu.
Konsep dasarnya: setiap vault ID punya label (dev, prod, test, dan sebagainya) dan sumber password (prompt untuk interaktif, atau path file). Contoh penggunaan vault ID saat menjalankan playbook:
ansible-playbook -i inventory.yml site.yml \
--vault-id dev@prompt \
--vault-id prod@~/.vault_pass_prod.txtInterpretasi perintah di atas:
dev@prompt — vault ID dev dengan password diminta interaktif.prod@~/.vault_pass_prod.txt — vault ID prod dengan password dibaca dari file ~/.vault_pass_prod.txt.Ansible akan meminta password dev di terminal, lalu otomatis mengambil password prod dari file. Playbook dijalankan dengan kedua vault secret tersebut.
Untuk memanfaatkan vault ID secara optimal, kita perlu memberi label saat mengenkripsi file. Caranya menggunakan opsi --vault-id pada perintah enkripsi:
ansible-vault encrypt group_vars/development.yml \
--vault-id dev@prompt
ansible-vault encrypt group_vars/production.yml \
--vault-id prod@~/.vault_pass_prod.txtSetelah itu, header file vault akan memuat label vault ID-nya:
$ANSIBLE_VAULT;1.2;AES256;prodHeader ;1.2;AES256;prod memberi tahu Ansible bahwa file ini dienkripsi dengan vault ID prod, sehingga saat playbook dijalankan, Ansible langsung mencocokkan dengan vault secret berlabel prod.
Warning
Jika kalian memakai multiple vault ID, pastikan selalu menyediakan semua vault secret yang dibutuhkan saat menjalankan playbook. Sebuah file yang dienkripsi dengan vault ID prod tidak akan bisa didekripsi hanya dengan password dev. Ketika secret tidak cocok, Ansible akan mencoba semua secret yang tersedia; jika semuanya gagal, playbook berhenti dengan error "Decryption failed".
Menggunakan Ansible Vault saja tidak cukup; cara kalian mengatur file dan password menentukan tingkat keamanannya. Berikut praktik terbaik yang lazim di industri:
1. Enkripsi per file, bukan seluruh playbook. Cukup enkripsi file vars atau group_vars yang berisi secret. Playbook itu sendiri tidak perlu dienkripsi, agar tetap bisa di-review di code review.
2. Simpan file vault password di luar repo. Di lokal, simpan di ~/.vault_pass.txt dengan chmod 600. Di CI/CD, simpan sebagai secret pada pipeline dan tulis sementara saat job berjalan.
3. Selalu tambahkan file password ke .gitignore. Contoh pola .gitignore:
# Jangan pernah meng-commit file password vault
.vault_pass*
*_vault_pass*.txt
*.vault.pass4. Gunakan ansible-vault rekey untuk mengganti password. Jika vault password pernah bocor atau ingin rotasi rutin, jangan mendekripsi-manual; gunakan rekey:
ansible-vault rekey group_vars/production.ymlrekey akan meminta password lama, lalu password baru dua kali, dan menulis ulang file dengan kunci baru — tanpa pernah membiarkan file terbuka sebagai plaintext di disk.
5. Atur permission ansible.cfg. Bisa juga dikonfigurasi di ansible.cfg agar default menggunakan vault ID, misalnya:
[defaults]
vault_password_file = ~/.vault_pass.txt6. Pisahkan secret per environment. Gunakan vault ID berbeda (dev, staging, prod) agar developer hanya punya akses ke secret yang relevan dengan pekerjaannya.
7. Rotasi secara berkala. Apapun alatnya, secret yang jarang dirotasi adalah risiko diam-diam. Buat jadwal rotasi vault password dan credential di dalamnya.
1. Meng-commit vault password file
Kesalahan paling fatal. Password vault adalah kunci master; bocor berarti semua file vault yang dilindunginya otomatis terbaca. Selalu .gitignore dan chmod 600.
2. Mengira menghapus file dari Git menghapusnya dari history
File plaintext yang pernah ter-commit tetap ada di git log -p. Jika secret sempat ter-commit, asumsikan sudah bocor dan segera rotasi, jangan hanya menghapus file.
3. Menjalankan playbook tanpa vault password
Error Attempting to decrypt but no vault secrets found atau no vault secrets were found that could decrypt terjadi karena secret tidak tersedia. Pastikan --ask-vault-pass, --vault-password-file, atau --vault-id diberikan.
4. Menggunakan vault ID yang tidak konsisten
File dienkripsi dengan vault ID prod, tapi saat run kalian hanya memberikan --vault-id dev@prompt. Pastikan label vault ID saat enkripsi dan saat eksekusi konsisten.
5. Memakai command/shell untuk mendekripsi
Jangan menulis ansible-vault decrypt di dalam task playbook hanya agar variabel terbaca — itu mengalahkan tujuan keamanan. Ansible sudah mendekripsi variabel secara otomatis saat runtime.
Pada episode 14 ini kita telah belajar bahwa menyimpan kredensial, API key, dan password dalam plaintext di repository Git adalah praktik yang sangat berbahaya karena riwayat Git bersifat permanen dan akses repo biasanya menyebar luas. Ansible Vault memecahkan masalah ini dengan enkripsi AES-256. Kita sudah menguasai seluruh CLI ansible-vault: encrypt, view, edit, decrypt, encrypt_string, dan rekey, menjalankan playbook terenkripsi dengan --ask-vault-pass maupun --vault-password-file, serta memanfaatkan multiple vault IDs (dev@prompt, prod@vault-pass-file) untuk memisahkan secret antar environment. Terakhir, kita membahas praktik terbaik seperti .gitignore untuk file password dan rotasi rutin dengan rekey.
Poin kunci yang perlu kalian bawa pulang:
ansible-vault encrypt, dan playbook tetap bisa memakainya tanpa perubahan.--ask-vault-pass untuk interaktif, --vault-password-file untuk otomatisasi/CI..gitignore + chmod 600.Dengan keamanan secret yang terjaga, automasi kalian kini tidak hanya rapi dan modular, tapi juga aman untuk dibawa ke produksi. Semakin besar infrastruktur, semakin terasa betapa pentingnya semua fondasi yang sudah kita bangun — termasuk kecepatan eksekusi, karena playbook dengan puluhan role dan ribuan task akan terasa lambat jika tidak dioptimalkan.
Di episode 15 selanjutnya kita akan membahas Performance Tuning & Execution Strategies — mengatur parallelism dengan forks, mengaktifkan SSH pipelining, memanfaatkan fact caching, serta memilih strategi eksekusi linear, free, dan serial untuk rolling update. Pastikan tetap semangat!