ansible
Ansible automation for server configuration, deployment, and infrastructure management. Use when user mentions "ansible", "ansible-playbook", "ansible-vault", "inventory", "playbook", "ansible role", "ansible galaxy", "configuration management", "server provisioning", "infrastructure automation", "ansible task", "ansible template", or automating server setup and deployment.
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o ansible.zip https://jpskill.com/download/6060.zip && unzip -o ansible.zip && rm ansible.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/6060.zip -OutFile "$d\ansible.zip"; Expand-Archive "$d\ansible.zip" -DestinationPath $d -Force; ri "$d\ansible.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
ansible.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
ansibleフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-17
- 取得日時
- 2026-05-17
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
[Skill 名] ansible
Ansible
SSH を介したエージェントレスな自動化です。管理対象ノードにエージェントをインストールする必要はありません。ターゲットに Python があり、SSH アクセスがあれば十分です。すべてのモジュールはデフォルトで冪等性を持っています。プレイブックを2回実行しても同じ結果が得られます。
アドホックコマンド
# すべてのホストに ping を実行
ansible all -m ping
# Web サーバーでコマンドを実行
ansible webservers -m command -a "uptime"
ansible webservers -m shell -a "df -h | grep /dev/sda"
# ファイルをコピー
ansible webservers -m copy -a "src=./app.conf dest=/etc/app.conf owner=root mode=0644"
# パッケージをインストール
ansible webservers -m apt -a "name=nginx state=present" --become
# サービスを管理
ansible webservers -m systemd -a "name=nginx state=restarted enabled=yes" --become
# ユーザーを作成
ansible all -m user -a "name=deploy shell=/bin/bash groups=sudo" --become
# ファクトを収集
ansible webservers -m setup -a "filter=ansible_distribution*"
インベントリ
静的インベントリ (hosts.ini)
[webservers]
web1.example.com ansible_host=10.0.1.10
web2.example.com ansible_host=10.0.1.11
[dbservers]
db1.example.com ansible_host=10.0.2.10 ansible_port=2222
[production:children]
webservers
dbservers
[webservers:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3
[all:vars]
ansible_ssh_private_key_file=~/.ssh/deploy_key
YAML インベントリ (inventory.yml)
all:
children:
webservers:
hosts:
web1.example.com:
ansible_host: 10.0.1.10
http_port: 8080
web2.example.com:
ansible_host: 10.0.1.11
dbservers:
hosts:
db1.example.com:
ansible_host: 10.0.2.10
vars:
db_port: 5432
ホスト変数とグループ変数
inventory/
hosts.yml
group_vars/
all.yml # すべてのホストに適用されます
webservers.yml # webservers グループに適用されます
production.yml
host_vars/
web1.example.com.yml
動的インベントリ
# AWS EC2
ansible-inventory -i aws_ec2.yml --list
# プラグイン設定 (aws_ec2.yml)
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
filters:
tag:Environment: production
keyed_groups:
- key: tags.Role
prefix: role
compose:
ansible_host: private_ip_address
プレイブックの構造
---
- name: Configure web servers
hosts: webservers
become: yes
vars:
app_port: 8080
app_user: www-data
pre_tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
mode: "0644"
notify: Restart nginx
- name: Ensure nginx is running
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
post_tasks:
- name: Verify nginx is responding
uri:
url: "http://localhost:{{ app_port }}"
status_code: 200
# プレイブックを実行
ansible-playbook site.yml
ansible-playbook site.yml -i inventory/hosts.yml
ansible-playbook site.yml --limit webservers
ansible-playbook site.yml --check # ドライラン
ansible-playbook site.yml --diff # ファイルの変更を表示
ansible-playbook site.yml -e "app_port=9090"
ansible-playbook site.yml --start-at-task="Deploy nginx config"
一般的なモジュール
# パッケージ管理
- apt:
name: [nginx, curl, git]
state: present
- yum:
name: httpd
state: latest
# ファイルとディレクトリ
- file:
path: /opt/app
state: directory
owner: deploy
group: deploy
mode: "0755"
- file:
path: /tmp/old_file
state: absent
# ファイルのコピー
- copy:
src: files/app.conf
dest: /etc/app/app.conf
owner: root
mode: "0644"
backup: yes
- copy:
content: "{{ lookup('template', 'config.j2') }}"
dest: /etc/app/config.yml
# テンプレート
- template:
src: templates/vhost.conf.j2
dest: /etc/nginx/conf.d/app.conf
validate: "nginx -t -c %s"
# サービス
- systemd:
name: nginx
state: restarted
daemon_reload: yes
enabled: yes
# ユーザーとグループ
- user:
name: deploy
shell: /bin/bash
groups: [sudo, docker]
append: yes
generate_ssh_key: yes
- authorized_key:
user: deploy
key: "{{ lookup('file', 'files/deploy.pub') }}"
# Git チェックアウト
- git:
repo: https://github.com/org/app.git
dest: /opt/app
version: main
force: yes
# Docker コンテナ
- docker_container:
name: redis
image: redis:7-alpine
state: started
restart_policy: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
# ファイルのダウンロード
- get_url:
url: https://example.com/app.tar.gz
dest: /tmp/app.tar.gz
checksum: sha256:abcdef1234567890
# コマンドの実行
- command: /opt/app/migrate.sh
args:
chdir: /opt/app
creates: /opt/app/.migrated
- shell: cat /etc/passwd | grep deploy
register: deploy_check
changed_when: false
# Cron ジョブ
- cron:
name: "Daily backup"
minute: "0"
hour: "2"
job: "/opt/scripts/backup.sh >> /var/log/backup.log 2>&1"
変数とファクト
# 変数の優先順位 (低いものから高いものへ):
# ロールデフォルト -> インベントリ変数 -> プレイブック変数 -> ロール変数
# -> include_vars -> set_fact -> extra vars (-e)
# 出力を登録
- command: whoami
register: current_user
- debug:
msg: "Running as {{ current_user.stdout }}"
# ファクトを動的に設定
- set_fact:
app_version: "{{ lookup('file', 'VERSION') }}"
deploy_timestamp: "{{ ansible_date_time.iso8601 }}"
# ファクトにアクセス
- debug:
msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"
- debug:
msg: "IP: {{ ansible_default_ipv4.address }}"
- debug:
msg: "Memory: {{ ansible_memtotal_mb }} MB"
# ファイルから変数をインクルード
- include_vars:
file: "{{ ansible_distribution | lower }}.yml"
Jinja
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Ansible
Agentless automation over SSH. No agents to install on managed nodes -- just Python on targets and SSH access. All modules are idempotent by default: running a playbook twice produces the same result.
Ad-Hoc Commands
# Ping all hosts
ansible all -m ping
# Run command on web servers
ansible webservers -m command -a "uptime"
ansible webservers -m shell -a "df -h | grep /dev/sda"
# Copy file
ansible webservers -m copy -a "src=./app.conf dest=/etc/app.conf owner=root mode=0644"
# Install package
ansible webservers -m apt -a "name=nginx state=present" --become
# Manage service
ansible webservers -m systemd -a "name=nginx state=restarted enabled=yes" --become
# Create user
ansible all -m user -a "name=deploy shell=/bin/bash groups=sudo" --become
# Gather facts
ansible webservers -m setup -a "filter=ansible_distribution*"
Inventory
Static Inventory (hosts.ini)
[webservers]
web1.example.com ansible_host=10.0.1.10
web2.example.com ansible_host=10.0.1.11
[dbservers]
db1.example.com ansible_host=10.0.2.10 ansible_port=2222
[production:children]
webservers
dbservers
[webservers:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3
[all:vars]
ansible_ssh_private_key_file=~/.ssh/deploy_key
YAML Inventory (inventory.yml)
all:
children:
webservers:
hosts:
web1.example.com:
ansible_host: 10.0.1.10
http_port: 8080
web2.example.com:
ansible_host: 10.0.1.11
dbservers:
hosts:
db1.example.com:
ansible_host: 10.0.2.10
vars:
db_port: 5432
Host and Group Variables
inventory/
hosts.yml
group_vars/
all.yml # Applies to every host
webservers.yml # Applies to webservers group
production.yml
host_vars/
web1.example.com.yml
Dynamic Inventory
# AWS EC2
ansible-inventory -i aws_ec2.yml --list
# Plugin config (aws_ec2.yml)
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
filters:
tag:Environment: production
keyed_groups:
- key: tags.Role
prefix: role
compose:
ansible_host: private_ip_address
Playbook Structure
---
- name: Configure web servers
hosts: webservers
become: yes
vars:
app_port: 8080
app_user: www-data
pre_tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
mode: "0644"
notify: Restart nginx
- name: Ensure nginx is running
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
post_tasks:
- name: Verify nginx is responding
uri:
url: "http://localhost:{{ app_port }}"
status_code: 200
# Run playbook
ansible-playbook site.yml
ansible-playbook site.yml -i inventory/hosts.yml
ansible-playbook site.yml --limit webservers
ansible-playbook site.yml --check # Dry run
ansible-playbook site.yml --diff # Show file changes
ansible-playbook site.yml -e "app_port=9090"
ansible-playbook site.yml --start-at-task="Deploy nginx config"
Common Modules
# Package management
- apt:
name: [nginx, curl, git]
state: present
- yum:
name: httpd
state: latest
# Files and directories
- file:
path: /opt/app
state: directory
owner: deploy
group: deploy
mode: "0755"
- file:
path: /tmp/old_file
state: absent
# Copy files
- copy:
src: files/app.conf
dest: /etc/app/app.conf
owner: root
mode: "0644"
backup: yes
- copy:
content: "{{ lookup('template', 'config.j2') }}"
dest: /etc/app/config.yml
# Templates
- template:
src: templates/vhost.conf.j2
dest: /etc/nginx/conf.d/app.conf
validate: "nginx -t -c %s"
# Services
- systemd:
name: nginx
state: restarted
daemon_reload: yes
enabled: yes
# Users and groups
- user:
name: deploy
shell: /bin/bash
groups: [sudo, docker]
append: yes
generate_ssh_key: yes
- authorized_key:
user: deploy
key: "{{ lookup('file', 'files/deploy.pub') }}"
# Git checkout
- git:
repo: https://github.com/org/app.git
dest: /opt/app
version: main
force: yes
# Docker containers
- docker_container:
name: redis
image: redis:7-alpine
state: started
restart_policy: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
# Download files
- get_url:
url: https://example.com/app.tar.gz
dest: /tmp/app.tar.gz
checksum: sha256:abcdef1234567890
# Run commands
- command: /opt/app/migrate.sh
args:
chdir: /opt/app
creates: /opt/app/.migrated
- shell: cat /etc/passwd | grep deploy
register: deploy_check
changed_when: false
# Cron jobs
- cron:
name: "Daily backup"
minute: "0"
hour: "2"
job: "/opt/scripts/backup.sh >> /var/log/backup.log 2>&1"
Variables and Facts
# Variable precedence (lowest to highest):
# role defaults -> inventory vars -> playbook vars -> role vars
# -> include_vars -> set_fact -> extra vars (-e)
# Register output
- command: whoami
register: current_user
- debug:
msg: "Running as {{ current_user.stdout }}"
# Set facts dynamically
- set_fact:
app_version: "{{ lookup('file', 'VERSION') }}"
deploy_timestamp: "{{ ansible_date_time.iso8601 }}"
# Access facts
- debug:
msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"
- debug:
msg: "IP: {{ ansible_default_ipv4.address }}"
- debug:
msg: "Memory: {{ ansible_memtotal_mb }} MB"
# Include vars from file
- include_vars:
file: "{{ ansible_distribution | lower }}.yml"
Jinja2 Templates
{# templates/nginx.conf.j2 #}
server {
listen {{ http_port | default(80) }};
server_name {{ server_name }};
{% if ssl_enabled | default(false) %}
listen 443 ssl;
ssl_certificate /etc/ssl/certs/{{ domain }}.crt;
ssl_certificate_key /etc/ssl/private/{{ domain }}.key;
{% endif %}
{% for location in app_locations %}
location {{ location.path }} {
proxy_pass http://{{ location.upstream }};
}
{% endfor %}
access_log /var/log/nginx/{{ server_name }}_access.log;
}
Common Jinja2 filters:
# Defaults
"{{ variable | default('fallback') }}"
# String
"{{ name | upper }}"
"{{ name | lower }}"
"{{ path | basename }}"
"{{ path | dirname }}"
# Lists
"{{ packages | join(', ') }}"
"{{ users | map(attribute='name') | list }}"
"{{ items | unique | sort }}"
# Data
"{{ dict_var | to_json }}"
"{{ dict_var | to_yaml }}"
"{{ 'password' | password_hash('sha512') }}"
# Ternary
"{{ 'yes' if enabled else 'no' }}"
Conditionals and Loops
# When conditional
- apt:
name: nginx
when: ansible_distribution == "Ubuntu"
- yum:
name: httpd
when: ansible_os_family == "RedHat"
- service:
name: app
state: restarted
when: deploy_result is changed
- debug:
msg: "Low disk"
when: ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first < 1073741824
# Loops
- user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- carol
- apt:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop:
- { name: nginx, state: present }
- { name: apache2, state: absent }
# Loop with index
- debug:
msg: "{{ index }}: {{ item }}"
loop: "{{ users }}"
loop_control:
index_var: index
label: "{{ item.name }}"
# Until retry loop
- uri:
url: http://localhost:8080/health
status_code: 200
register: health
until: health.status == 200
retries: 30
delay: 5
Error Handling
# Ignore errors
- command: /opt/app/check.sh
ignore_errors: yes
register: check_result
# Custom failure condition
- command: /opt/app/status.sh
register: status
failed_when: "'ERROR' in status.stdout"
changed_when: "'UPDATED' in status.stdout"
# Block / rescue / always (try/catch/finally)
- block:
- name: Deploy application
git:
repo: https://github.com/org/app.git
dest: /opt/app
version: "{{ app_version }}"
- name: Run migrations
command: ./migrate.sh
args:
chdir: /opt/app
rescue:
- name: Rollback on failure
command: ./rollback.sh
args:
chdir: /opt/app
- name: Send failure alert
mail:
to: ops@example.com
subject: "Deploy failed on {{ inventory_hostname }}"
body: "Rolled back to previous version."
always:
- name: Restart application
systemd:
name: app
state: restarted
Tags
- name: Install packages
apt:
name: nginx
tags: [packages, nginx]
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags: [config, nginx]
- name: Deploy application
git:
repo: https://github.com/org/app.git
dest: /opt/app
tags: [deploy]
ansible-playbook site.yml --tags "deploy"
ansible-playbook site.yml --skip-tags "packages"
ansible-playbook site.yml --tags "config,nginx"
ansible-playbook site.yml --list-tags
Roles
Directory Structure
roles/
webserver/
defaults/main.yml # Default variables (lowest precedence)
vars/main.yml # Role variables (high precedence)
tasks/main.yml # Task list
handlers/main.yml # Handlers
templates/ # Jinja2 templates
files/ # Static files
meta/main.yml # Role metadata and dependencies
Example Role
# roles/webserver/defaults/main.yml
http_port: 80
server_name: localhost
document_root: /var/www/html
# roles/webserver/tasks/main.yml
---
- name: Install nginx
apt:
name: nginx
state: present
- name: Deploy config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: Reload nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/default
dest: /etc/nginx/sites-enabled/default
state: link
# roles/webserver/handlers/main.yml
---
- name: Reload nginx
systemd:
name: nginx
state: reloaded
# roles/webserver/meta/main.yml
---
dependencies:
- role: common
- role: firewall
vars:
open_ports: [80, 443]
# Use role in playbook
- hosts: webservers
become: yes
roles:
- common
- { role: webserver, http_port: 8080 }
- role: ssl
when: ssl_enabled | default(false)
Ansible Galaxy
# Install roles
ansible-galaxy install geerlingguy.docker
ansible-galaxy install -r requirements.yml
# Install collections
ansible-galaxy collection install community.docker
ansible-galaxy collection install -r requirements.yml
# Initialize new role
ansible-galaxy role init my_role
# List installed
ansible-galaxy list
ansible-galaxy collection list
# requirements.yml
roles:
- name: geerlingguy.docker
version: "6.1.0"
- name: geerlingguy.certbot
- src: https://github.com/org/custom-role.git
name: custom_role
version: main
collections:
- name: community.docker
version: ">=3.0.0"
- name: amazon.aws
version: "7.0.0"
Ansible Vault
# Encrypt a file
ansible-vault encrypt vars/secrets.yml
# Decrypt
ansible-vault decrypt vars/secrets.yml
# Edit encrypted file in-place
ansible-vault edit vars/secrets.yml
# View without decrypting
ansible-vault view vars/secrets.yml
# Change encryption password
ansible-vault rekey vars/secrets.yml
# Encrypt a single string
ansible-vault encrypt_string 'SuperSecret123' --name 'db_password'
# Run playbook with vault
ansible-playbook site.yml --ask-vault-pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# vars/secrets.yml (encrypted content)
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
6234613839383...
# ansible.cfg - avoid typing password every time
[defaults]
vault_password_file = ~/.vault_pass
Docker and Container Management
# Requires: ansible-galaxy collection install community.docker
- name: Deploy containerized app
hosts: docker_hosts
become: yes
collections:
- community.docker
tasks:
- name: Install Docker
include_role:
name: geerlingguy.docker
- name: Pull image
docker_image:
name: myapp
tag: "{{ app_version }}"
source: pull
- name: Run app container
docker_container:
name: myapp
image: "myapp:{{ app_version }}"
state: started
restart_policy: unless-stopped
ports:
- "8080:8080"
env:
DATABASE_URL: "{{ db_url }}"
REDIS_URL: "{{ redis_url }}"
volumes:
- app_data:/data
networks:
- name: app_network
- name: Docker compose deployment
docker_compose_v2:
project_src: /opt/app
state: present
pull: always
Testing with Molecule
pip install molecule molecule-docker
# Initialize
cd roles/webserver
molecule init scenario --driver-name docker
# Test lifecycle
molecule create # Create test instance
molecule converge # Run role against instance
molecule verify # Run tests
molecule destroy # Clean up
molecule test # Full cycle (create -> converge -> verify -> destroy)
# molecule/default/molecule.yml
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: ubuntu
image: ubuntu:22.04
pre_build_image: false
command: /sbin/init
privileged: true
- name: rocky
image: rockylinux:9
command: /sbin/init
privileged: true
provisioner:
name: ansible
verifier:
name: ansible
# molecule/default/verify.yml
---
- name: Verify
hosts: all
tasks:
- name: Check nginx is running
command: systemctl is-active nginx
changed_when: false
- name: Check port 80
wait_for:
port: 80
timeout: 5
Performance Tuning
# ansible.cfg
[defaults]
forks = 20 # Parallel host connections (default 5)
gathering = smart # Cache facts, don't re-gather
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400
host_key_checking = False
stdout_callback = yaml # Readable output
[ssh_connection]
pipelining = True # Reduce SSH operations (requires requiretty off)
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
# Async tasks for long operations
- name: Long running update
apt:
upgrade: dist
async: 3600 # Max runtime in seconds
poll: 10 # Check every 10 seconds (0 = fire and forget)
# Limit fact gathering
- hosts: webservers
gather_facts: no
tasks:
- setup:
gather_subset:
- network
- hardware
# Free strategy (don't wait for all hosts per task)
- hosts: webservers
strategy: free
tasks:
- name: Independent task
apt:
name: curl
For Mitogen (3-7x speedup), install mitogen and set strategy_plugins and strategy = mitogen_linear in ansible.cfg.
Common Patterns
Deploy Application
- hosts: webservers
become: yes
serial: "30%" # Rolling deploy
max_fail_percentage: 10
pre_tasks:
- name: Remove from load balancer
uri:
url: "http://lb.internal/api/remove/{{ inventory_hostname }}"
method: POST
roles:
- app_deploy
post_tasks:
- name: Add back to load balancer
uri:
url: "http://lb.internal/api/add/{{ inventory_hostname }}"
method: POST
- name: Health check
uri:
url: "http://localhost:{{ app_port }}/health"
status_code: 200
retries: 10
delay: 3
Setup Users and SSH
- name: Configure users
hosts: all
become: yes
tasks:
- name: Create users
user:
name: "{{ item.name }}"
groups: "{{ item.groups | default([]) }}"
shell: /bin/bash
loop: "{{ admin_users }}"
- name: Add SSH keys
authorized_key:
user: "{{ item.name }}"
key: "{{ item.ssh_key }}"
loop: "{{ admin_users }}"
- name: Sudoers entry
lineinfile:
path: /etc/sudoers.d/{{ item.name }}
line: "{{ item.name }} ALL=(ALL) NOPASSWD:ALL"
create: yes
mode: "0440"
validate: "visudo -cf %s"
loop: "{{ admin_users }}"
when: item.sudo | default(false)