ansible-coder について
ansible-coderは、少数のサーバーから複雑なインフラまでを対象に、Ansibleで設定・保守を行うためのスキルです。単純なフラット構成を基本とし、Cloud-InitとAnsibleの使い分けも示します。
主な機能
- 01単一のフラットなPlaybookを基本とする構成
- 02静的・Terraform生成Inventoryの例
- 03パッケージ・セキュリティ・システム設定
- 04Galaxy依存関係の管理
- 05チェックモードとホスト指定実行
活用シーン
- 01少数のWeb・データベースサーバーの設定
- 02既存サーバーへの設定の再適用
- 03Docker、SSH、Fail2ban、ファイアウォールの構成
- 04Terraform出力からのInventory生成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill ansible-coderインストール後、Claude Code で/ansible-coderを入力して読み込まれたか確認します。
同梱ファイルreferences/kamal-playbook.mdreferences/provision-script.md
詳細
Ansible コーダー
⚠️ シンプルさを最優先 — デフォルトはフラットな構成
必ず最もシンプルな方法から始めてください。明示的に求められた場合にのみ、複雑さを追加してください。
シンプル(デフォルト)と過剰設計
| 項目 | ✅ シンプル(デフォルト) | ❌ 過剰設計 |
|---|---|---|
| Playbook | インラインタスクを含む Playbook 1 つ | 複数の Playbook + カスタムロール |
| ロール | Galaxy ロール(geerlingguy.*)を使用 | 簡単なタスク用にカスタムロールを作成 |
| インベントリ | 単一の hosts.ini | 複数のインベントリ + group_vars の階層 |
| 変数 | Playbook 内、または単一の vars ファイルに記述 | group_vars/host_vars に分散 |
| ファイル数 | 合計約3~5ファイル | ネストしたディレクトリ内に20以上のファイル |
シンプルな方法を使う場合(ケースの90%)
- 1~5台のサーバーをセットアップする
- 標準的なスタック(Docker、nginx、fail2ban、ufw)を使用する
- 単一の環境、または同一構成のサーバーを使用する
- ホストごとの複雑な条件ロジックがない
複雑な構成が妥当な場合(ケースの10%)
- 構成が大きく異なる大規模なサーバーフリート
- ロールの分離が必要な複数チーム
- 依存関係を伴う複雑なオーケストレーション
- ユーザーが明示的にモジュール構成を求めている
ルール:すべてを200行の Playbook 1つに収められるなら、そうしてください。
Ansible と Cloud-Init の使い分け
| Cloud-Init を使う場合 | Ansible を使う場合 |
|---|---|
| 初回起動のみ | 既存サーバーの構成を再実行する |
| シンプルなパッケージのインストール | 複雑な複数ステップの構成 |
| 基本的なユーザー作成 | ロールベースの構成 |
| 不変のインフラストラクチャ | 更新が必要な変更可能なサーバー |
経験則: 初期プロビジョニングには Cloud-Init、継続的な管理には Ansible を使います。
ディレクトリ構成
シンプルな構成(デフォルト)
infra/ansible/
├── playbook.yml # Single playbook with all tasks inline
├── requirements.yml # Galaxy dependencies (geerlingguy.*, etc.)
├── hosts.ini # Inventory (git-ignored)
└── hosts.ini.example # Inventory template
複雑な構成(妥当な場合のみ)
infra/ansible/
├── playbook.yml # Main playbook
├── requirements.yml # Galaxy dependencies
├── hosts.ini # Inventory (git-ignored)
├── hosts.ini.example # Inventory template
├── group_vars/
│ └── all.yml # Shared variables
└── roles/
└── custom_role/
├── tasks/main.yml
├── handlers/main.yml
└── templates/
インベントリ
静的インベントリ
# hosts.ini
[web]
192.168.1.1 ansible_user=root
[db]
192.168.1.2 ansible_user=root
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Terraform からの動的インベントリ
# Generate inventory from Terraform output
SERVER_IP=$(cd infra && tofu output -raw server_ip)
cat > infra/ansible/hosts.ini << EOF
[web]
$SERVER_IP ansible_user=root
EOF
Playbook の構成
基本的な Playbook
---
- name: Configure web servers
hosts: web
become: true
vars:
timezone: "UTC"
swap_size_mb: "2048"
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Install packages
ansible.builtin.apt:
name:
- docker.io
- fail2ban
- ufw
state: present
ロールを使用する場合
---
- name: Configure web servers
hosts: web
become: true
vars:
security_autoupdate_reboot: true
security_autoupdate_reboot_time: "03:00"
roles:
- role: geerlingguy.swap
when: ansible_swaptotal_mb < 1
- role: geerlingguy.docker
- role: security
よくあるタスク
パッケージ管理
- name: Install required packages
ansible.builtin.apt:
name:
- curl
- ca-certificates
- gnupg
- fail2ban
- ufw
- ntp
state: present
update_cache: true
Docker のインストール
- name: Check if Docker is installed
ansible.builtin.command: docker --version
register: docker_installed
ignore_errors: true
changed_when: false
- name: Install Docker via convenience script
ansible.builtin.shell: curl -fsSL https://get.docker.com | sh
when: docker_installed.rc != 0
args:
creates: /usr/bin/docker
- name: Ensure Docker is running
ansible.builtin.systemd:
name: docker
state: started
enabled: true
SSH の強化
- name: Disable SSH password authentication
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PasswordAuthentication"
line: "PasswordAuthentication no"
notify: Restart ssh
- name: Disable SSH root login with password
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PermitRootLogin"
line: "PermitRootLogin prohibit-password"
notify: Restart ssh
handlers:
- name: Restart ssh
ansible.builtin.systemd:
name: ssh # Ubuntu uses 'ssh', not 'sshd'
state: restarted
Fail2ban
- name: Configure fail2ban for SSH
ansible.builtin.copy:
dest: /etc/fail2ban/jail.local
content: |
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
mode: "0644"
notify: Restart fail2ban
- name: Ensure fail2ban is running
ansible.builtin.systemd:
name: fail2ban
state: started
enabled: true
handlers:
- name: Restart fail2ban
ansible.builtin.systemd:
name: fail2ban
state: restarted
UFW ファイアウォール
- name: Set UFW default policies
community.general.ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
loop:
- { direction: incoming, policy: deny }
- { direction: outgoing, policy: allow }
- name: Allow specified ports through UFW
community.general.ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- 22 # SSH
- 80 # HTTP
- 443 # HTTPS
- name: Enable UFW
community.general.ufw:
state: enabled
カーネルのチューニング
- name: Configure sysctl for performance
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: true
loop:
- { name: vm.swappiness, value: "10" }
- { name: net.core.somaxconn, value: "65535" }
タイムゾーン
- name: Set timezone
community.general.timezone:
name: "{{ timezone }}"
Snap の削除(Ubuntu の肥大化対策)
- name: Remove snapd
ansible.builtin.apt:
name: snapd
state: absent
purge: true
ignore_errors: true
- name: Remove snap directories
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /snap
- /var/snap
- /var/lib/snapd
Galaxy の依存関係
requirements.yml
---
roles:
- name: geerlingguy.swap
version: 2.0.0
- name: geerlingguy.docker
version: 7.4.1
collections:
- name: community.general
- name: ansible.posix
インストール
ansible-galaxy install -r requirements.yml --force
Playbook の実行
基本的な実行
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i hosts.ini playbook.yml
変数を指定して実行
ansible-playbook -i hosts.ini playbook.yml \
-e "timezone=Europe/Berlin" \
-e "swap_size_mb=4096"
ドライラン
ansible-playbook -i hosts.ini playbook.yml --check --diff
特定のホストに限定
ansible-playbook -i hosts.ini playbook.yml --limit web
完全な Kamal デプロイサーバー用 Playbook については、Kamal サーバーの準備を参照してください。
Terraform-Ansible-Kamal プロビジョニングパイプラインについては、Terraform との統合を参照してください。
トラブルシューティング
| 問題 | 原因 | 対処方法 |
|---|---|---|
ssh: connect refused | サーバーの準備ができていない | 待機するか、ファイアウォールを確認する |
Permission denied | SSH キーが間違っている | -i で指定する |
sudo: password required | ユーザーに NOPASSWD が必要 | become_method: sudo を使用する |
| ハンドラーが実行されない | タスクによる変更がなかった | changed_when: true を使用する |
| モジュールが見つからない | コレクションが不足している | requirements.yml からインストールする |
コメント
Markdown 対応