📚 連載:Ansibleが理解できない理由はLinuxにあった【OS編】第4回:【Permission deniedの正体】Linuxユーザーと権限の仕組み
Linuxの仕組みからAnsibleを理解するシリーズです。
0️⃣ Ansibleの仕組み
1️⃣ Linuxの構造(Kernel / Shell / Filesystem)
2️⃣ command not foundの原因:PATH
3️⃣ SSH接続できない理由:鍵認証とポート
4️⃣ Permission deniedの原因:ユーザーと権限
5️⃣ サービスが起動しない理由:systemd
6️⃣ cronが動かない理由:PATH問題
7️⃣ ディスク満杯になる理由
8️⃣ サーバーが遅くなる理由
🗺️ 初めての方・シリーズの全体像を知りたい方はこちら
本記事は、OSの仕組みからAnsible設計までを繋ぐ連載シリーズの一部です。
「どこから読み始めればいいか」あるいは、「OS/Shell/Ansible編の関係性」 について把握されたい場合は、以下の統合ガイドで整理しています。
📑 【OS編】全体のまとめはこちら
→ Ansibleが理解できない理由はLinuxにあった【OS編】まとめ
📑 連載の移動
前の記事:【OS編】第3回 | 次の記事:【OS編】第5回
シリーズ全体構造(学習 × 問題解決)
本シリーズは
「理解(各記事)」と「問題解決(逆引き辞典)」を組み合わせて
スキルを身につける構成になっています。
この図は、どこから学び、どこに進めばよいかを示した“ロードマップ”です。
📍 現在の位置
現在はこの図の「OS編 第4回」になります
📍 はじめに:この記事のスタンス
SSHの壁を突破し、サーバーに入った後に直面するのが次のエラーです。
-
「ログインはできているのに、ファイルの編集で Permission denied になる」
-
「手動で sudo すれば動くのに、Ansible経由だと失敗する」
-
「とりあえず become: yes を付けているが、裏で何が起きているか説明できない」
⚠️ 注意事項
この記事は、Linuxの権限(パーミッション)やユーザー管理を学術的に網羅する「教科書」ではありません。
目的はただひとつです。
Ansibleで Permission denied が出たとき、
「どのユーザーの、どの権限が足りないのか」を即座に特定することです。
「ログインには成功している。だが、操作が制限される」
この実務上の壁を突破するために、Linuxの「ユーザー・所有者・権限」という3つの属性と、Ansibleの become の挙動を紐解いていきます。
📋 目次
- 前回の振り返り(第3回)
- 逆引き辞典との連動
- Linuxのユーザー:全ての操作は「誰か」に紐付く
- パーミッション構造:アクセス制御リストの解析
- なぜ Permission denied が起きるのか
- sudo とは何か:一時的な権限昇格の仕組み
- Ansibleの become:sudo 操作の自動化
- Ansibleと権限:実務における定義の整理
- 実務における権限管理の典型的な課題
- まとめ:事実に基づく「調査の原則」
- 次回予告
- 連載一覧:Ansibleが理解できない理由はLinuxにあった
1. 前回の振り返り(第3回)
前回の記事では、サーバーまでの通信経路である SSH接続 について解説しました。
UNREACHABLE は、「ネットワーク・設定・認証」のいずれかで通信が止まっている状態でした。
今回は、その先のステップです。サーバー内部に入った後、「特定のファイルやコマンドを触る権利」 があるかどうかの問題を整理します。
2. 逆引き辞典との連動
具体的なエラー名から原因を特定したい場合は、以下の逆引き辞典を活用してください。
Ansibleが理解できない理由はLinuxにあった :【保存版】Ansibleトラブル逆引き辞典|エラー別の原因と解決フローまとめ
- まず「逆引き辞典」で該当ステップを特定する
- 次に「本編(各連載記事)」で仕組みを理解する
3. Linuxのユーザー:全ての操作は「誰か」に紐付く
Linuxにおける「ユーザー」は、操作を行う主体を定義するものです。これらは全て /etc/passwd という構成ファイル(ユーザー定義リスト)によって一元管理されています。
実務上、パーミッションを理解するために整理すべきユーザーは以下の3種類です。
| ユーザー種別 | 主な役割 | 特徴 |
|---|---|---|
| root | 管理者 | 全てのファイルに対して「rwx」を無視して操作できる最強の権限。 |
| ログインユーザー | 人間がSSH接続する用 |
ubuntu や ansibleuser 等。通常は自身のホームディレクトリ以外の操作権限が制限されている。 |
| システムユーザー | サービス実行用 |
nginx, postgres 等。特定のミドルウェアを動作させるために定義され、通常は直接ログインを行わない。 |
🔗 Ansibleとの関係
Ansibleがどのユーザーコンテキストで処理を行うかは、以下の2段階で決定されます。
-
接続フェーズ:
ansible_user(例: ansibleuser)としてSSHセッションを確立する。 -
実行フェーズ:
become: yesの指定により、root 等の別ユーザーへと特権昇格(Privilege Escalation)を行う。
Permission denied の多くは、この「実行主体のユーザー」と、次章で解説する「対象ファイルの所有属性」の不一致に起因します。
4. パーミッション構造:アクセス制御リストの解析
Linuxの全てのファイルおよびディレクトリには、「どの主体に対し、いかなる操作を許可するか」 を定義した属性が付随しています。Ansibleによる操作が拒否された際、最初に行うべきはこの属性情報の確認です。
ls -l /etc/nginx/nginx.conf
- 出力結果の構造解析
ls -lの出力には、アクセス可否を決定する「3つの属性区分」と「3つの権限種別」が定義されています。
- rw- r-- r-- 1 root root 1200 nginx.conf
^^^ ^^^ ^^^ ^^^^ ^^^^
(A) (B) (C) (1) (2) (3)その他
① 3つの属性(誰が)
| 項目 | 意味 | 実務での見方 |
|---|---|---|
| (1) 所有者 (Owner) | ファイルの権限保持者 | プログラムの実行ユーザーや root が設定される。 |
| (2) 所有グループ (Group) | 権限を共有するグループ | 複数ユーザー間で共通の操作権限を付与する際に利用される。 |
| (3) その他 (Others) | 上記(1)(2)以外の全員 | Ansible(特権昇格なしの状態)は、通常ここに含まれる。 |
② 3つの権限種別(操作内容)
上記(1)〜(3)の各区分に対し、以下の権限(Permission)が割り当てられます。
-
r (read): ファイルの読み取り許可。
-
w (write): ファイルの書き込み・編集許可。
-
x (execute): プログラムとしての実行許可。
5. なぜ Permission denied が起きるのか
このエラーが起きる理由は、第3回の「鍵リスト(authorized_keys)」と同じロジックです。
「属性リストのどこにAnsibleの実行ユーザーが該当し、何の権利が載っているか」 をチェックすれば、原因は自ずと見えてきます。
5-1. 判定のメカニズム
例えば、Ansibleの copy モジュール等で /etc/nginx/nginx.conf を編集しようとした場合、Linux内部では以下の 「優先順位に基づいた照合」 が行われています。
| 判定ステップ | 対象(リスト) | 許可内容 (rwx) | あなた(Ansible)の結果 |
|---|---|---|---|
| Step 1 | (A) 所有者(root) | rw- (読み書き可) | Ansibleは root ではない → 次へ |
| Step 2 | (B) グループ(root) | r-- (読み取りのみ) | Ansibleはグループ外 → 次へ |
| Step 3 | (C) その他(Ansible) | r-- (読み取りのみ) | ここに該当! |
💡 結論:なぜ制限されたのか
- Ansible(ansible_user: ubuntuなど) は、(1)所有者でも(2)グループメンバーでもないため、自動的に 「(3)その他」 として扱われます。
- しかし「その他」のリストには
r--しか許可が載っていません。 - 結果:Ansibleが書き込み(w)をしようとした瞬間に、Linux側から制限(Permission denied)されます。
5-2. 【検証】あえて「特権なし」で実行する
まず、何の対策もしていない状態のプレイブックで実行してみます。
修正前:特権指定なし(fail_copy.yml)
- name: 権限エラーを発生させる実験
hosts: test_servers
# become: yes がないため、一般ユーザー権限で動作する
tasks:
- name: 管理者権限が必要な場所にファイルをコピーする
ansible.builtin.copy:
src: ./nginx.conf
dest: /etc/nginx/nginx.conf
出力結果:
(ansible) [ansible@localhost ansible-test]$ ansible-playbook -i ../inventory.ini fail_copy.yml
TASK [管理者権限なしでNginxの設定ファイルをコピーする] ****************************************
fatal: [192.168.1.21]: FAILED! => {
"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},
"changed": false,
"checksum": "68e3f2711ad342e0eab8fd6a0f53c8c08bc09111",
"msg": "Destination /etc/nginx not writable"
}
このように、Linuxのパーミッション制限によって書き込みが拒否されます。
このログから、以下の技術的な事実が確認できます。
- メッセージ(msg)の定義
表示されている"msg": "Destination /etc/nginx not writable"は、Ansibleが対象パスへの書き込み権限を確認し、制限されたことを示す定義済みのメッセージです。OSが返却するPermission denied(Errno 13)を、Ansibleが「宛先が書き込み不可の状態である」と具体的なステータスに変換して出力しています。 - 処理の進行状況(checksum)
checksumが表示されていることは、コントロールノード側でのファイル読み取りおよびハッシュ計算、そしてリモートノードへのデータ転送までは正常に完了していることを示しています。 - エラー発生のフェーズ
ステータスがUNREACHABLEではなくFAILEDであることから、SSH認証によるログインは成功しています。最終フェーズである「/etc/nginxへのファイル配置(書き込み操作)」において、Linuxのパーミッション制限により処理が停止したことが確定できます。
結論として、このエラーの原因は「SSH認証の失敗」ではなく、「実行ユーザーの権限と対象ディレクトリのパーミッション設定の不一致」にあります。
6. sudo とは何か:一時的な権限昇格の仕組み
「(3)その他」の立場では、システム設定の変更(w)やインストール(x)ができません。しかし、すべてのファイルの所有者を自分に変えるのは、セキュリティ上も運用上も現実的ではありません。
そこで、自分のユーザーのまま 「一時的に root(特権ユーザー)の権限を借りて実行する」 仕組みが sudo です。
-
sudo なし: あなた(一般ユーザー)の権限で実行 → 制限
-
sudo あり: あなたが root に「なり代わって」実行 → 許可
この「なり代わり」ができるかどうかは、/etc/sudoers という 「昇格許可リスト」 にあなたの名前が載っているかどうかで決まります。Linuxはここでも「リスト照合」を行っています。
7. Ansibleの become:sudo 操作の自動化
Ansibleで Permission denied を回避するために使う become: yes は、内部的に sudo 操作を自動化するスイッチです。
7-1. 処理フローの全体像
Ansibleが裏側で行っているステップを分解します。
[コントロールノード]
↓
SSH接続(ansible_user: ansibleuser)
↓
一般ユーザーとしてログイン(この時点では権限不足)
↓
(タスク実行)
↓
become: yes を検知 → 内部で sudo コマンドを発行
↓
root(特権ユーザー)へ昇格
↓
ファイルの配置(書き込み)に成功
- 重要な事実: Ansibleは独自の特殊な通信を行っているわけではなく、「SSHでログインした後に、人間と同じように sudo を叩く」 という手順を自動で行っているだけです。
7-2. 【検証】become: yes を記述して再実行
第5セクションでエラーになったプレイブックに対し、become: yes を記述して、特権昇格を伴う実行へと構成を変更します。
修正後:特権昇格を有効化(fail_copy.yml)
- name: 権限エラーを解消する実験
hosts: test_servers
become: yes # ここで特権昇格を有効化
tasks:
- name: 管理者権限でNginxの設定ファイルをコピーする
ansible.builtin.copy:
src: ./nginx.conf
dest: /etc/nginx/nginx.conf
実行結果:
(ansible) [ansible@localhost ansible-test]$ ansible-playbook -i ../inventory.ini fail_copy.yml
TASK [管理者権限でNginxの設定ファイルをコピーする] ****************************************
changed: [192.168.1.21]
PLAY RECAP ********************************************************************************
192.168.1.21 : ok=1 changed=1 unreachable=0 failed=0 ...
先ほどは FAILED で停止していましたが、今回は changed となり、正常にファイルが配置されました。
💡 なぜ成功したのか
-
昇格の実行:
become: yesにより、Ansibleがリモート先でsudoを実行しました。 -
権限の充足:
ansibleuserが一時的にroot(所有者)の権限で動作したため、判定メカニズムの Step 1(所有者判定) において書き込み許可(w)が得られました。 -
状態の変更: その結果、OSによる制限を受けることなく、
/etc/nginx/nginx.confの更新が完了しました。
7-3. リモートノード側での最終確認
処理の結果、リモートサーバー内の状態がどう変化したかを物理的に確認します。
[root@localhost ~]# ls -l /etc/nginx/
合計 4
-rw-r--r--. 1 root root 2334 4月 25 13:19 nginx.conf
ファイルの所有者が root になっている点に注目してください。
一般ユーザーでログインしても、become: yes を介することで、最終的に root 権限でファイルが書き込まれたことが、この属性表示からも裏付けられます。
8. Ansibleと権限:実務における定義の整理
実務において、Ansibleの変数とLinuxのシステム構成がどのように紐付いているかを整理します
| Linuxの概念 | Ansibleの変数名 | 役割 |
|---|---|---|
| リモートログインユーザー | ansible_user | SSH認証を行い、セッションを開始するユーザー |
| 特権昇格(Privilege Escalation) | become: yes | ログイン後に特定の権限への昇格を試行する設定 |
| 昇格先のユーザー | become_user | 昇格後の実行コンテキストとなるユーザー(デフォルトは root) |
💡 実行ユーザーとシステムユーザーの分離
実務上の誤解として、「Nginxの設定ファイルを操作するために ansible_user: nginx を指定する」というケースが見受けられますが、これは技術的に以下の理由で推奨されません。
-
SSHログインの可否:
nginxやapacheといったシステムユーザーは、セキュリティ上の観点から「ログインシェルを持たない(/sbin/nologin等)」設定となっており、外部からのSSH接続自体が制限されているのが一般的です。 -
適切な運用フロー:
まずはSSH接続権限を持つ一般ユーザー(ansible_user)としてセッションを確立し、その後にAnsibleのbecomeプロセスを通じて、必要な権限(rootまたは特定のシステムユーザー)へと処理を移行させるのが正しい構成となります。
9. 実務における権限管理の典型的な課題
Ansibleを用いた自動化において、権限設定に起因する代表的な構成ミスとその対策を整理します
1. 特権昇格指定(become)の欠落
/etc ディレクトリ配下の設定ファイル変更や、パッケージマネージャーによるインストール等、root権限を要するタスクにおいて become: yes の記述が漏れているケースです。
-
技術的影響: 第5セクションで詳述した通り、OSによる書き込み制限(Permission denied)が発生し、タスクが異常終了します。
-
対策: 管理者権限を必要とするタスク、あるいはプレイ全体に対して、明示的に
become: yesを定義し、適切な実行コンテキストを確保してください。
2. ファイル属性(所有者・グループ)の定義不足
copy モジュール等でファイルを配置した際、明示的な指定がないと所有者が root(昇格後のユーザー)となります。これにより、アプリケーション実行ユーザー(nginx 等)がファイルを読み込めなくなる事象が発生します。
-
技術的影響: 配置されたファイルのパーミッションにおいて、実行ユーザーが「その他(Others)」に分類され、読み取り権限(r)が不足している場合にアプリケーションが正常に動作しません。
-
対策: タスク内で owner および group パラメーターを用い、対象ユーザー・グループを明示的に指定してください。
3. 不適切なパーミッション設定(chmod 777)
権限エラーの回避を目的として、ディレクトリやファイルに 777(すべてのユーザーに全権限を付与)を設定する運用です。
-
技術的影響: 第3セクションで解説したLinuxのセキュリティモデルを無効化する行為であり、重大な脆弱性に繋がります。
-
対策: 最小権限の原則(Principle of Least Privilege)に基づき、所有者・グループの属性を正しく定義した上で、必要最小限の権限(例:ファイルは
644、ディレクトリは755)を設定してください。
10. まとめ:事実に基づく「調査の原則」
Permission denied に直面した際、Ansibleのパラメーターを場当たり的に変更するのではなく、まずは以下の3ステップでOS側の「事実」を特定してください。
これは第4セクションで解説したパーミッションの判定構造(誰が・何を・どの権限で)を、そのまま調査手順へと落とし込んだものです。
【Permission denied の調査手順】
-
プロセスの実行主体(誰)を特定する
-
ansible_userおよびbecomeの有無から、リモート側での実効ユーザーを確定させる。
-
-
対象オブジェクトの属性(何に)を確認する
-
ls -lコマンドにより、対象の所有者・グループ・パーミッション設定を物理的に確認する。
-
-
権限の不整合(なぜ)を解消する
- 実行主体が属性リストの認可範囲に含まれていない場合、以下のいずれか、または両方を選択する。
・becomeによる適切な権限への昇格。
・owner/group/modeによる対象の属性修正。
- 実行主体が属性リストの認可範囲に含まれていない場合、以下のいずれか、または両方を選択する。
調査の原則
Permission denied は、Ansibleというツールのエラーではなく、「Linuxカーネルによる正当なアクセス制限」 です。
第2回のPATH、第3回の鍵リストの検証と同様に、「ls -l という属性リストにおいて、自身がどの階層に該当し、いかなる権限を付与されているか」。この一点を事実として確認することが、解決への最短経路となります。
「Ansibleの設定を疑う前に、Linuxの属性リストを確認する」
この原則を徹底することで、権限に関するトラブルシューティングの精度は飛躍的に向上します。
📚 シリーズを順番に読む
このシリーズでは Linuxの仕組みからAnsibleを理解する ことを目的にしています。
| 回 | 内容 |
|---|---|
| 第0回 | Ansibleの仕組み |
| 第1回 | Linuxの構造(Kernel / Shell / Filesystem) |
| 第2回 | command not foundの原因:PATH |
| 第3回 | SSH |
| 第4回 | Permission deniedの原因 |
| 第5回 | systemd |
| 第6回 | cron |
| 第7回 | ディスク容量 |
| 第8回 | サーバーが遅い原因 |
11. 次回予告
権限設定(Privilege Escalation)の課題を解消し、次なるステップはアプリケーションサービスの起動です。
しかし、正常に構成されたプレイブックであっても、実行時に以下のエラーに直面するケースが多々あります。
"FAILED! => msg: Job for nginx.service failed because the control process exited with error code."
Ansibleにはサービス制御を司る以下のモジュールが存在します。
-
ansible.builtin.service
-
ansible.builtin.systemd
「適切な権限を付与し、become: yes も定義した。それにもかかわらず、なぜサービスユニットの起動に失敗するのか?」
次回は、Linuxにおけるサービス管理の標準アーキテクチャである 「systemd」 の構造と、Ansibleによる制御メカニズムを詳述します。OS側のサービス管理の「裏側」を理解し、トラブルシューティングの精度をさらに高めていきましょう。
次回:【第5回】サービスが起動しない理由:systemdの仕組みを理解する
📑 連載の移動
前の記事:【OS編】第3回 | 次の記事:【OS編】第5回
📑 【OS編】全体のまとめはこちら
→ Ansibleが理解できない理由はLinuxにあった【OS編】まとめ
🗺️ 初めての方・シリーズの全体像を知りたい方はこちら
本記事は、OSの仕組みからAnsible設計までを繋ぐ連載シリーズの一部です。
「どこから読み始めればいいか」あるいは、「OS/Shell/Ansible編の関係性」 について把握されたい場合は、以下の統合ガイドで整理しています。
12. 連載一覧:Ansibleが理解できない理由はLinuxにあった
| 回数とタイトル | 内容(概要) |
|---|---|
| Ansibleが理解できない理由はLinuxにあった【OS編】:【保存版】Ansibleトラブル逆引き辞典(Linux / SSH / Shellエラー対応 | Ansibleで発生するエラー(UNREACHABLE / Permission denied / command not found など)を「エラーから逆引き」で調べられる実務向け記事。各回の内容と対応しており、トラブル時の入口として使える。 |
| 第0回:【なぜAnsibleは理解できないのか】仕組みを分解してみる | Ansibleは「Linux操作の自動化」ツール。Ansible → SSH → Shell → Linux の構造を理解し、シリーズ全体の土台を作る。 |
| 第1回:【なぜLinuxが分からないと詰むのか】Kernel / Shell / Filesystemの全体像 | Linuxの基本構造を理解することで、Ansibleが内部で何をしているのか(Shell実行・プロセス・ファイル操作)を把握できるようになる。 |
| 第2回:【Ansibleでハマる】command not foundの原因はPATHだった(環境変数の正体) | Ansible実行時に発生する「command not found」の原因はPATHにある。環境変数の仕組みを理解しないとエラーを解決できない。 |
| 第3回:AnsibleのSSH接続が失敗すると UNREACHABLE エラーになる。(Connection refused / Permission denied / Timeout など) | AnsibleのSSH接続が失敗すると UNREACHABLE エラーになる。SSH(鍵認証・ポート・Firewall)を理解することで原因を特定できる。 |
| 第4回:【Permission deniedの正体】Linuxユーザーと権限の仕組み | Ansibleのbecome(sudo)で発生する Permission denied の原因はLinux権限にある。ユーザー・グループ・権限の仕組みを理解する。 |
| 第5回:【サービスが起動しない理由】systemdの仕組みを理解する | Ansibleのservice / systemdタスクが失敗する原因はLinux側にある。systemdの仕組みを理解することで原因を特定できる。 |
| 第6回:【cronが動かない理由】手動では動くのに失敗する原因 | Ansibleで設定したcronが動かない原因は環境差分(PATHなど)にある。cron特有の実行環境を理解することで解決できる。 |
| 第7回:【No space left on device】ディスク容量不足の原因と調査方法(df / du / log) | Ansible実行時のディスク不足エラーはLinuxのログ肥大化や容量管理が原因。df / duを使った調査方法を解説する。 |
| 第8回:【サーバーが遅い】原因の見つけ方(CPU / メモリ / プロセス) | Ansible実行が遅い・失敗する原因はサーバー負荷の可能性がある。CPU・メモリ・プロセスの見方を理解して原因を特定する。 |