Ansible Vaultでシークレットを安全に管理する方法|パスワードファイルや暗号化変数の実践例

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Ansible > Ansible Vaultでシークレットを安全に管理する方法|パスワードファイルや暗号化変数の実践例
「playbookにパスワードを直書きしてしまっている……」
そう気づいた瞬間、ぞっとした経験はないでしょうか。Ansibleはサーバーを自動設定できる便利なツールですが、DBのパスワードやAPIキーをplaybookにベタ書きしてしまうと、Gitにコミットした瞬間に認証情報が漏洩するリスクが生まれます。

この記事では、Ansibleに標準搭載されている Ansible Vault を使って、パスワードや秘密鍵などのシークレット情報を安全に暗号化・管理する方法を解説します。vault-passwordファイルによるパスワードレス実行、変数ファイルの部分暗号化、group_varsとの分離設計、CI/CD連携まで実践的な手順をカバーします。

この記事のポイント

・ansible-vault encrypt でファイルをAES256で丸ごと暗号化してGitに安全にコミットできる
・vault_password_fileで対話入力なし・自動実行が可能になる
・vars.ymlとvault.ymlを分けると変数名を平文で検索しながら値だけ暗号化できる
・vault-idで本番・開発のVaultパスワードを環境ごとに分離できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Ansible Vaultとは何か

Ansible Vaultは、playbookやインベントリファイルに含まれる機密情報を AES256で暗号化 するAnsible標準機能です。ansible-coreに含まれているので、追加インストールは不要です。

「変数ファイルにパスワードを書いてGitにpushしてしまった」という事故は意外と多く発生します。しかも問題は単に「見られる」だけではありません。Gitの履歴に一度でも入ると、ブランチを削除しても git log や git reflog でたどれてしまいます。GitHubにpushした後でリポジトリをプライベートに変えても、Gitオブジェクト自体は残ります。こうした問題を設計段階で防ぐのがAnsible Vaultです。

暗号化の対象は主に次の3種類です。

・変数ファイル全体(vars/secrets.yml を丸ごと暗号化)
・変数の値だけ(!vault | タグで1変数だけ暗号化)
・任意のファイル(SSL証明書の秘密鍵ファイルなど)

よく混同されますが、Vaultはあくまで「保管時の暗号化」です。playbookが実行されるとき、Ansibleはメモリ上でのみ復号します。ディスクには常に暗号化された状態で残ります。

# 動作確認環境 # Control Node: RHEL 9.4 / Rocky Linux 9.4 # Managed Node: Rocky Linux 9.4(SSH接続可能なテスト用VM) # Ansible: ansible-core 2.16.x # 確認コマンド $ ansible --version ansible [core 2.16.9]

基本的な使い方|ファイルを暗号化する

1. 暗号化したいファイルを用意する

まず、DBパスワードなどの秘密情報を変数ファイルにまとめます。

# vars/secrets.yml(暗号化前) db_password: "P@ssw0rd!secret" api_key: "sk-xxxxxxxxxxxxxxxxxxxx" smtp_password: "smtpSecret123"

2. ansible-vault encrypt でファイルを暗号化する

$ ansible-vault encrypt vars/secrets.yml New Vault password: Confirm New Vault password: Encryption successful

暗号化後のファイルを確認すると、中身が完全に変換されています。

$ cat vars/secrets.yml $ANSIBLE_VAULT;1.1;AES256 39623163393264653535633630363832356335623564623163396161373766353831303635323665 6662353630336637316236663266626536343834636333370a306163326135393136616166646665 ...(以下省略)...

この状態でGitにコミットしても、Vaultのパスワードを知らない限り中身を読めません。なお、新規の暗号化ファイルを一から作成したい場合は ansible-vault create を使うとエディタが開いてそのまま書き込めます。

3. 暗号化ファイルを使ってplaybookを実行する

暗号化したファイルをplaybookから参照する場合、実行時に --ask-vault-pass または --vault-password-file が必要です。

# パスワードを対話入力する場合 $ ansible-playbook -i inventory/hosts site.yml -e @vars/secrets.yml --ask-vault-pass # パスワードファイルを指定する場合(CI/CD向け) $ ansible-playbook -i inventory/hosts site.yml -e @vars/secrets.yml --vault-password-file ~/.vault_pass.txt

vault-password-fileで自動実行する

CI/CDパイプラインや cronからの自動実行では、対話入力ができません。そこで vault-password-file を使ってパスワードをファイルから読み込ませます。

1. パスワードファイルを作成する

# パスワードファイルを作成(改行なしで書く) $ echo -n 'YourVaultPassword' > ~/.vault_pass.txt # 権限を本人のみ読み取り可能にする $ chmod 600 ~/.vault_pass.txt # 確認 $ ls -la ~/.vault_pass.txt -rw------- 1 ansible ansible 17 Jun 30 10:00 /home/ansible/.vault_pass.txt

2. ansible.cfg に設定して毎回の指定を省略する

プロジェクトルートの ansible.cfg に書いておくと、実行のたびに --vault-password-file を付けなくて済みます。

# ansible.cfg [defaults] inventory = inventory/hosts vault_password_file = ~/.vault_pass.txt

# ansible.cfg 設定後はオプションなしで実行できる $ ansible-playbook site.yml -e @vars/secrets.yml PLAY [web servers] ************************************************************ ... PLAY RECAP ************************************************************ 192.168.10.10 : ok=8 changed=3 unreachable=0 failed=0 skipped=0

重要: .vault_pass.txt は絶対に .gitignore に追加してください。パスワードファイル自体がGitに入ってしまうと本末転倒です。

# .gitignore に追加必須 ~/.vault_pass.txt .vault_pass.txt

3. GitHub ActionsでVaultパスワードを安全に渡す

GitHub ActionsではリポジトリのSecretsにVaultパスワードを登録し、実行時にファイルに書き出して使います。

# .github/workflows/deploy.yml name: Deploy on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Ansible run: pip install ansible - name: Write vault password file run: echo "${{ secrets.ANSIBLE_VAULT_PASSWORD }}" > .vault_pass.txt - name: Run Playbook run: | ansible-playbook -i inventory/production site.yml --vault-password-file .vault_pass.txt - name: Remove vault password file if: always() run: rm -f .vault_pass.txt

secrets.ANSIBLE_VAULT_PASSWORD はGitHubのリポジトリ設定(Settings > Secrets and variables > Actions)に登録したシークレットです。パスワードファイルは if: always() で確実に削除します。

変数ファイルの一部だけを暗号化する(inline vault)

ファイル全体を暗号化すると「どの変数が何のために使われているか」が分からなくなります。変数名は見せておいて、値だけ暗号化 する方法が !vault タグを使った inline vault です。

1. 値だけを暗号化する

# 変数の「値」だけを暗号化(-n で改行なし) $ ansible-vault encrypt_string --stdin-name 'db_password' New Vault password: (入力) Confirm New Vault password: (入力) Reading plaintext input from stdin. (ctrl-d to end input) P@ssw0rd!secret ← 暗号化したい値を入力してCtrl+D db_password: !vault | $ANSIBLE_VAULT;1.1;AES256 38663930303137363666343663376237653233313238316231336137303666656231326430626630 3738323664613831316631336237643363383965313032350a643961333761666362616631633034 ... Encryption successful

2. vars/main.yml に埋め込む

出力された db_password: !vault | ブロックをそのまま変数ファイルに貼り付けます。

# vars/main.yml(変数名は平文・値だけ暗号化) db_host: "db01.example.com" db_name: "app_production" db_user: "appuser" db_password: !vault | $ANSIBLE_VAULT;1.1;AES256 38663930303137363666343663376237653233313238316231336137303666656231326430626630 3738323664613831316631336237643363383965313032350a643961333761666362616631633034 ...

これでGitを見た人は「db_passwordという変数がある」とわかりますが、中身の値は読めません。チームでの可読性と安全性を両立できる方法です。

group_varsとVaultファイルの分離設計(推奨パターン)

変数ファイルを丸ごと暗号化すると、中の変数名を grep で検索できなくなります。大きなプロジェクトで「この変数はどこで定義されているか」を追いかける際、暗号化ファイルが増えると手間が跳ね上がります。

この問題を解消する定番パターンが、変数定義ファイル(vars.yml)と暗号化ファイル(vault.yml)を分ける 設計です。

1. ディレクトリ構成

# group_vars 配下を vars.yml + vault.yml の2ファイルに分ける group_vars/ ├── production/ │ ├── vars.yml # 平文の変数定義(Gitにコミットする) │ └── vault.yml # 暗号化済みの実値(Gitにコミットするが暗号化済み) └── staging/ ├── vars.yml └── vault.yml

2. vars.yml に変数名と参照先を書く

vars.yml には変数の「名前」と「vault変数への参照」だけを平文で書きます。

# group_vars/production/vars.yml(平文・grep検索可能) db_host: "db01.example.internal" db_port: 5432 db_user: "appuser" db_password: "{{ vault_db_password }}" # vault.yml の値を参照 api_key: "{{ vault_api_key }}" smtp_password: "{{ vault_smtp_password }}"

3. vault.yml に実値を書いて暗号化する

vault.yml には実際の秘密情報を書き、vault_ プレフィックスを付けた変数名にします。

# group_vars/production/vault.yml(暗号化前の平文内容) # このファイルを ansible-vault encrypt で暗号化してからGitにコミットする vault_db_password: "P@ssw0rd_Prod_2024" vault_api_key: "sk-xxxxxxxxxxxxxxxxxxxx" vault_smtp_password: "smtpSecret123"

# vault.yml を暗号化してからコミット $ ansible-vault encrypt group_vars/production/vault.yml New Vault password: Confirm New Vault password: Encryption successful # 暗号化済みを確認してから git add する $ head -1 group_vars/production/vault.yml $ANSIBLE_VAULT;1.1;AES256 ← 先頭行で暗号化済みを確認 $ git add group_vars/production/vault.yml $ git commit -m "Add encrypted production vault variables"

この構造にすることで、grep "db_password" group_vars/ を実行すれば vars.yml から変数名がすぐ見つかります。実際の値は vault.yml に隔離されているので平文では露出しません。Playbookは db_password という変数名で参照するだけでよく、Vault依存の書き方になりません。

roleで使う場合は vault_ロール名_変数名 のように2段のプレフィックスを付けると、複数roleが並んでいる環境での変数名衝突を防げます。

暗号化ファイルの確認・編集

1. ansible-vault view で中身を確認する

# 復号して表示(ファイルは暗号化されたまま) $ ansible-vault view vars/secrets.yml db_password: "P@ssw0rd!secret" api_key: "sk-xxxxxxxxxxxxxxxxxxxx" smtp_password: "smtpSecret123"

2. ansible-vault edit で直接編集する

# デフォルトエディタ($EDITOR)が開く。保存時に自動再暗号化される $ ansible-vault edit vars/secrets.yml # エディタを指定する場合 $ EDITOR=vim ansible-vault edit vars/secrets.yml

3. ansible-vault rekey でパスワードを変更する

Vaultパスワードを定期ローテーションする際に使います。

# パスワードを変更する $ ansible-vault rekey vars/secrets.yml Vault password: (現在のパスワード) New Vault password: (新しいパスワード) Confirm New Vault password: Rekey successful

複数Vaultパスワードの使い分け(vault-id)

開発・本番で同じVaultパスワードを使い回していると、開発者が本番のパスワードを知ることになります。--vault-id を使うとVaultファイルに「ラベル」を付けて環境ごとに異なるパスワードで管理できます。Ansible 2.4以降で導入された機能です。

# 暗号化時に vault-id を指定 $ ansible-vault encrypt --vault-id dev@~/.vault_dev.txt vars/dev_secrets.yml $ ansible-vault encrypt --vault-id prod@~/.vault_prod.txt vars/prod_secrets.yml # 実行時に両方指定(複数の vault-id を渡せる) $ ansible-playbook site.yml --vault-id dev@~/.vault_dev.txt --vault-id prod@~/.vault_prod.txt

この設計のメリットは権限分離にあります。開発者には dev@ のパスワードだけ渡し、prod@ のパスワードは運用チームだけが知る、という運用が実現できます。本番環境用パスワードファイルをVaultサーバーやAWS Secrets Managerに保管し、開発用とは分離するパターンがよく使われます。CI/CDパイプラインも実行環境のラベルに対応するパスワードだけを渡せばよくなります。

実際のplaybook構成例

Vaultを組み込んだrole構成の典型例を示します。

# プロジェクト構成 project/ ├── ansible.cfg ← vault_password_file を設定 ├── inventory/ │ └── hosts ├── group_vars/ │ └── production/ │ ├── vars.yml ← 平文変数(公開可) │ └── vault.yml ← 暗号化(Gitコミット可) ├── vars/ │ └── secrets.yml ← 暗号化(既存構成の場合) ├── roles/ │ └── mysql/ │ ├── tasks/ │ │ └── main.yml │ └── templates/ │ └── my.cnf.j2 └── site.yml

# site.yml --- - name: Configure MySQL server hosts: db_servers vars_files: - group_vars/production/vars.yml - group_vars/production/vault.yml # Vault で暗号化済み roles: - mysql

# roles/mysql/templates/my.cnf.j2 [mysqld] bind-address = 127.0.0.1 # Vault から取得した変数を使用 # ディスクには暗号化済み・メモリ展開時だけ平文 password = {{ db_password }}

トラブルシュート|よくあるエラーと対処

「ERROR! Decryption failed」が出る

Vaultパスワードが間違っているか、パスワードファイルの末尾に余分な改行が入っている場合に発生します。

# 改行なしでパスワードファイルを作成し直す $ printf 'YourVaultPassword' > ~/.vault_pass.txt # または $ echo -n 'YourVaultPassword' > ~/.vault_pass.txt # 改行が入っているか確認 $ xxd ~/.vault_pass.txt | tail -3 00000010: 6f72 6400 ord. ← 0a(改行コード)がなければOK

vault-idを使っている場合は、指定したラベルが暗号化時と一致しているかも確認してください。

# ファイルがVault形式かどうかは先頭行で確認できる $ head -1 group_vars/production/vault.yml $ANSIBLE_VAULT;1.1;AES256 ← 暗号化済み # vault-id付きで復号できるか確認 $ ansible-vault view --vault-id prod@prompt group_vars/production/vault.yml Vault password (prod): (パスワード入力)

「WARNING: Ansible is in a world writable directory」が出る

ansible.cfgが置かれているディレクトリの権限が777になっていると出るセキュリティ警告です。

# ディレクトリ権限を修正 $ chmod 755 /path/to/project

「vault_password_file does not exist」が出る

ansible.cfg に指定したパスのファイルがない状態です。

# パスを絶対パスで確認 $ ls -la ~/.vault_pass.txt -rw------- 1 ansible ansible 17 Jun 30 10:00 /home/ansible/.vault_pass.txt # ansible.cfg のパスが正しいか確認 $ grep vault_password_file ansible.cfg vault_password_file = ~/.vault_pass.txt

「ansible.cfg の vault_password_file が効かない」

ansible.cfg の読み込み優先順は「カレントディレクトリ > ~/.ansible.cfg > /etc/ansible/ansible.cfg」です。意図しない設定ファイルが読まれていないか確認します。

# どの ansible.cfg が読まれているか確認 $ ansible --version ansible [core 2.16.9] config file = /home/user/projects/ansible/ansible.cfg ← 読まれているファイル ... # ANSIBLE_CONFIG 環境変数で明示的に指定もできる $ export ANSIBLE_CONFIG=/path/to/ansible.cfg

本記事のまとめ

やりたいこと コマンド
ファイルを暗号化 ansible-vault encrypt vars/secrets.yml
新規暗号化ファイルを作成 ansible-vault create vars/secrets.yml
値だけを暗号化 ansible-vault encrypt_string --stdin-name '変数名'
中身を確認(ファイルは暗号化維持) ansible-vault view vars/secrets.yml
暗号化ファイルを編集 ansible-vault edit vars/secrets.yml
Vaultパスワードを変更 ansible-vault rekey vars/secrets.yml
ファイルを復号(元に戻す) ansible-vault decrypt vars/secrets.yml
パスワードファイルを指定して実行 ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
複数Vaultを使い分け ansible-playbook site.yml --vault-id dev@~/.vault_dev.txt
Ansible Vaultを使えば、GitリポジトリにシークレットをコミットしてもAES256で守られます。まずは ansible-vault encrypt でsecrets.ymlを暗号化するところから始めて、慣れたら group_vars 配下を vars.yml と vault.yml に分ける設計に移行するのがおすすめです。チームが大きくなる前に vault-id で本番・開発を分離しておくと、権限管理が格段に楽になります。

Ansibleの基本的なplaybookの書き方や実行方法については、ansible-playbookコマンドの使い方|インベントリ・playbook作成からLinuxサーバー自動化の実践例まで をあわせてご覧ください。

また、構成管理の全体設計については Ansibleのinventory・role・module設計|現場で崩れない構成管理の基礎 も参考にしてください。

Ansible Vaultを使ったシークレット管理を含め、Ansibleの実践スキルを体系的に習得したい方はぜひ詳細をご覧ください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。