mcpField
A
ansible-coder

ansible-coder

github.com/majesticlabs-devクラウド・DevOps5072 回インストール7 週間前に更新
リポジトリ

ansible-coder について

ansible-coderは、少数のサーバーから複雑なインフラまでを対象に、Ansibleで設定・保守を行うためのスキルです。単純なフラット構成を基本とし、Cloud-InitとAnsibleの使い分けも示します。

主な機能

  1. 01単一のフラットなPlaybookを基本とする構成
  2. 02静的・Terraform生成Inventoryの例
  3. 03パッケージ・セキュリティ・システム設定
  4. 04Galaxy依存関係の管理
  5. 05チェックモードとホスト指定実行

活用シーン

  1. 01少数のWeb・データベースサーバーの設定
  2. 02既存サーバーへの設定の再適用
  3. 03Docker、SSH、Fail2ban、ファイアウォールの構成
  4. 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 deniedSSH キーが間違っている-i で指定する
sudo: password requiredユーザーに NOPASSWD が必要become_method: sudo を使用する
ハンドラーが実行されないタスクによる変更がなかったchanged_when: true を使用する
モジュールが見つからないコレクションが不足しているrequirements.yml からインストールする

コメント