Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configuration management and automation with Ansible. Use when the user needs to write playbooks, manage inventory, create roles, use Ansible Vault for secrets, or orchestrate multi-server deployments across environments.
.claude/skills/terminalskills-ansible/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 266% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 197% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 102% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 67% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 128% | 0% |
Ansible is an agentless automation tool for configuration management, application deployment, and orchestration. It uses SSH to connect to managed nodes and executes tasks defined in YAML playbooks.
bash# Install Ansible via pip pip install ansible # Verify installation ansible --version
ini# inventory/production.ini — Production inventory with groups [webservers] web1.example.com ansible_host=10.0.1.10 web2.example.com ansible_host=10.0.1.11 [databases] db1.example.com ansible_host=10.0.2.10 [all:vars] ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/deploy_key ansible_python_interpreter=/usr/bin/python3
yaml# inventory/dynamic_aws.yml — Dynamic AWS EC2 inventory plugin plugin: amazon.aws.aws_ec2 regions: - us-east-1 - us-west-2 keyed_groups: - key: tags.Environment prefix: env - key: instance_type prefix: type filters: tag:Managed: ansible compose: ansible_host: private_ip_address
yaml# playbooks/webserver.yml — Configure Nginx web servers --- - name: Configure web servers hosts: webservers become: true vars: nginx_port: 80 app_root: /var/www/app pre_tasks: - name: Update apt cache apt: update_cache: true cache_valid_time: 3600 tasks: - name: Install Nginx apt: name: nginx state: present - name: Deploy Nginx configuration template: src: templates/nginx.conf.j2 dest: /etc/nginx/sites-available/default owner: root group: root mode: "0644" notify: Restart Nginx - name: Ensure app directory exists file: path: "{{ app_root }}" state: directory owner: www-data group: www-data mode: "0755" - name: Deploy application files synchronize: src: files/app/ dest: "{{ app_root }}/" notify: Restart Nginx - name: Ensure Nginx is running service: name: nginx state: started enabled: true handlers: - name: Restart Nginx service: name: nginx state: restarted
yaml# playbooks/deploy-app.yml — Rolling deployment with serial execution --- - name: Deploy application hosts: webservers become: true serial: 2 max_fail_percentage: 25 pre_tasks: - name: Remove from load balancer uri: url: "http://lb.example.com/api/deregister/{{ inventory_hostname }}" method: POST roles: - role: app-deploy vars: app_version: "{{ deploy_version | default('latest') }}" post_tasks: - name: Health check uri: url: "http://{{ inventory_hostname }}:{{ app_port }}/health" status_code: 200 retries: 5 delay: 10 - name: Re-register with load balancer uri: url: "http://lb.example.com/api/register/{{ inventory_hostname }}" method: POST
yaml# roles/common/tasks/main.yml — Common server baseline role --- - name: Set timezone timezone: name: "{{ server_timezone | default('UTC') }}" - name: Install common packages apt: name: - curl - wget - vim - htop - unzip - jq - fail2ban state: present - name: Configure SSH hardening template: src: sshd_config.j2 dest: /etc/ssh/sshd_config validate: sshd -t -f %s notify: Restart SSH - name: Configure firewall rules ufw: rule: allow port: "{{ item }}" proto: tcp loop: "{{ allowed_ports | default(['22']) }}" - name: Enable UFW ufw: state: enabled policy: deny
yaml# roles/common/defaults/main.yml — Default variables for common role --- server_timezone: UTC allowed_ports: - "22" - "80" - "443" ntp_servers: - 0.pool.ntp.org - 1.pool.ntp.org
bash# Create encrypted variables file ansible-vault create group_vars/production/vault.yml # Encrypt existing file ansible-vault encrypt secrets.yml # Edit encrypted file ansible-vault edit group_vars/production/vault.yml # Run playbook with vault password ansible-playbook site.yml --ask-vault-pass # Use password file (for CI/CD) ansible-playbook site.yml --vault-password-file ~/.vault_pass
yaml# group_vars/production/vault.yml — Encrypted production secrets --- vault_db_password: supersecretpassword vault_api_key: abc123def456 vault_ssl_cert: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
yaml# group_vars/production/vars.yml — Reference vault variables with prefix --- db_password: "{{ vault_db_password }}" api_key: "{{ vault_api_key }}"
ini# ansible.cfg — Project-level Ansible configuration [defaults] inventory = inventory/ roles_path = roles/ retry_files_enabled = false host_key_checking = false stdout_callback = yaml forks = 20 timeout = 30 [privilege_escalation] become = true become_method = sudo become_ask_pass = false [ssh_connection] pipelining = true ssh_args = -o ControlMaster=auto -o ControlPersist=60s
bash# Run playbook against specific inventory ansible-playbook -i inventory/production.ini playbooks/webserver.yml # Limit to specific hosts ansible-playbook playbooks/deploy.yml --limit web1.example.com # Dry run (check mode) ansible-playbook playbooks/deploy.yml --check --diff # Run ad-hoc commands ansible webservers -m shell -a "uptime" ansible all -m ping # List hosts in a group ansible-inventory --list --yaml # Run with extra variables ansible-playbook deploy.yml -e "deploy_version=2.1.0 env=production" # Tags for selective execution ansible-playbook site.yml --tags "configuration,packages" ansible-playbook site.yml --skip-tags "slow_tasks"
nginx# templates/nginx.conf.j2 — Nginx virtual host template server { listen {{ nginx_port }}; server_name {{ ansible_fqdn }}; root {{ app_root }}; {% if ssl_enabled | default(false) %} listen 443 ssl; ssl_certificate {{ ssl_cert_path }}; ssl_certificate_key {{ ssl_key_path }}; {% endif %} location / { proxy_pass http://127.0.0.1:{{ app_port }}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } access_log /var/log/nginx/{{ inventory_hostname }}_access.log; error_log /var/log/nginx/{{ inventory_hostname }}_error.log; }
yaml# playbooks/conditional-tasks.yml — Tasks with conditionals and loops --- - name: Conditional and loop examples hosts: all become: true tasks: - name: Install packages based on OS family apt: name: "{{ item }}" state: present loop: "{{ debian_packages }}" when: ansible_os_family == "Debian" - name: Create users from list user: name: "{{ item.name }}" groups: "{{ item.groups | join(',') }}" shell: "{{ item.shell | default('/bin/bash') }}" state: present loop: "{{ users }}" no_log: true - name: Wait for service readiness uri: url: "http://localhost:{{ app_port }}/health" register: health until: health.status == 200 retries: 10 delay: 5
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 10,614 | 7,175 | -32% | 1 | 1 | 0% | 2,254 | 3,661 | +62% | 0 | 0 | — |
case-02 | pass→pass | 8,547 | 7,230 | -15% | 1 | 1 | 0% | 1,994 | 4,031 | +102% | 0 | 0 | — |
case-03 | pass→pass | 9,500 | 4,942 | -48% | 1 | 1 | 0% | 1,988 | 3,324 | +67% | 0 | 0 | — |
case-04 | pass→pass | 6,959 | 6,711 | -4% | 1 | 1 | 0% | 1,617 | 3,681 | +128% | 0 | 0 | — |
case-05 | fail→pass | 3,947 | 3,524 | -11% | 1 | 1 | 0% | 802 | 2,936 | +266% | 0 | 0 | — |
case-06 | fail→pass | 5,005 | 3,659 | -27% | 1 | 1 | 0% | 983 | 2,917 | +197% | 0 | 0 | — |
case-07 | pass→pass | 11,341 | 4,341 | -62% | 1 | 1 | 0% | 2,264 | 3,013 | +33% | 0 | 0 | — |
case-08 | pass→pass | 10,539 | 10,814 | +3% | 1 | 1 | 0% | 2,375 | 4,309 | +81% | 0 | 0 | — |
case-09 | pass→pass | 3,533 | 2,709 | -23% | 1 | 1 | 0% | 646 | 2,579 | +299% | 0 | 0 | — |
case-10 | pass→pass | 4,762 | 2,564 | -46% | 1 | 1 | 0% | 921 | 2,682 | +191% | 0 | 0 | — |
case-11 | pass→pass | 2,697 | 2,238 | -17% | 1 | 1 | 0% | 448 | 2,518 | +462% | 0 | 0 | — |
case-12 | pass→pass | 4,803 | 3,799 | -21% | 1 | 1 | 0% | 1,018 | 3,041 | +199% | 0 | 0 | — |
case-13 | fail→fail | 4,124 | 3,754 | -9% | 1 | 1 | 0% | 820 | 2,870 | +250% | 0 | 0 | — |
case-14 | fail→fail | 8,171 | 4,335 | -47% | 1 | 1 | 0% | 1,596 | 3,093 | +94% | 0 | 0 | — |
case-15 | pass→pass | 4,241 | 2,843 | -33% | 1 | 1 | 0% | 883 | 2,760 | +213% | 0 | 0 | — |
case-16 | pass→pass | 3,989 | 2,930 | -27% | 1 | 1 | 0% | 671 | 2,686 | +300% | 0 | 0 | — |
case-17 | pass→pass | 4,203 | 2,368 | -44% | 1 | 1 | 0% | 744 | 2,572 | +246% | 0 | 0 | — |
case-18 | pass→pass | 2,968 | 2,093 | -29% | 1 | 1 | 0% | 515 | 2,507 | +387% | 0 | 0 | — |
case-19 | pass→pass | 3,047 | 2,078 | -32% | 1 | 1 | 0% | 568 | 2,604 | +358% | 0 | 0 | — |
case-20 | pass→pass | 6,741 | 5,060 | -25% | 1 | 1 | 0% | 1,356 | 3,274 | +141% | 0 | 0 | — |
case-21 | pass→pass | 6,002 | 5,635 | -6% | 1 | 1 | 0% | 1,303 | 3,456 | +165% | 0 | 0 | — |
case-22 | pass→pass | 22,206 | 6,959 | -69% | 1 | 1 | 0% | 2,152 | 3,638 | +69% | 0 | 0 | — |
case-23 | pass→pass | 4,851 | 3,376 | -30% | 1 | 1 | 0% | 772 | 2,807 | +264% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.