All skills
Skillintermediate

Common Ansible Module Usage Patterns

- name: Install specific version ansible.builtin.apt: name: nginx=1.18.0-0ubuntu1 state: present

Claude Code Knowledge Pack7/10/2026

Overview

Common Ansible Module Usage Patterns

Core Modules (ansible.builtin)

Package Management

ansible.builtin.package (Universal)

- name: Install package (OS-agnostic)
  ansible.builtin.package:
    name: nginx
    state: present

ansible.builtin.apt (Debian/Ubuntu)

- name: Install package with apt
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true
    cache_valid_time: 3600

- name: Install specific version
  ansible.builtin.apt:
    name: nginx=1.18.0-0ubuntu1
    state: present

- name: Install multiple packages
  ansible.builtin.apt:
    name:
      - nginx
      - postgresql
      - redis-server
    state: present

ansible.builtin.dnf (RHEL 8+/CentOS 8+) - Recommended

# NOTE: Use ansible.builtin.dnf for RHEL 8+ and CentOS 8+
# ansible.builtin.yum is deprecated in favor of dnf for modern RHEL systems

- name: Install package with dnf
  ansible.builtin.dnf:
    name: nginx
    state: present
    update_cache: true

- name: Install from specific repository
  ansible.builtin.dnf:
    name: nginx
    state: present
    enablerepo: epel

- name: Install multiple packages
  ansible.builtin.dnf:
    name:
      - nginx
      - postgresql
      - redis
    state: present

ansible.builtin.yum (RHEL 7/CentOS 7 - Legacy)

# NOTE: Only use for RHEL 7/CentOS 7 systems
# For RHEL 8+ use ansible.builtin.dnf instead

- name: Install package with yum (legacy systems)
  ansible.builtin.yum:
    name: nginx
    state: present
    update_cache: true

- name: Install from specific repository (legacy)
  ansible.builtin.yum:
    name: nginx
    state: present
    enablerepo: epel

File Operations

ansible.builtin.file

# Create directory
- name: Create directory
  ansible.builtin.file:
    path: /opt/app/config
    state: directory
    mode: '0755'
    owner: appuser
    group: appgroup
    recurse: true

# Create symbolic link
- name: Create symlink
  ansible.builtin.file:
    src: /opt/app/current
    dest: /opt/app/releases/v1.2.3
    state: link

# Remove file/directory
- name: Remove file
  ansible.builtin.file:
    path: /tmp/tempfile
    state: absent

# Set permissions
- name: Set file permissions
  ansible.builtin.file:
    path: /etc/app/secret.key
    mode: '0600'
    owner: root
    group: root

ansible.builtin.copy

# Copy file from control node
- name: Copy configuration file
  ansible.builtin.copy:
    src: files/nginx.conf
    dest: /etc/nginx/nginx.conf
    mode: '0644'
    owner: root
    group: root
    backup: true
    validate: 'nginx -t -c %s'

# Copy with inline content
- name: Create file with content
  ansible.builtin.copy:
    content: |
      server {
        listen 80;
        server_name example.com;
      }
    dest: /etc/nginx/sites-available/example
    mode: '0644'

# Remote copy (on target host)
- name: Copy file on remote host
  ansible.builtin.copy:
    src: /tmp/source.txt
    dest: /opt/destination.txt
    remote_src: true

ansible.builtin.template

- name: Deploy configuration from template
  ansible.builtin.template:
    src: templates/app_config.j2
    dest: /etc/app/config.yml
    mode: '0644'
    owner: appuser
    group: appgroup
    backup: true
    validate: '/usr/bin/app validate %s'

ansible.builtin.fetch

- name: Fetch file from remote to control node
  ansible.builtin.fetch:
    src: /var/log/app/error.log
    dest: /tmp/logs/{{ inventory_hostname }}/
    flat: true

ansible.builtin.lineinfile

- name: Ensure line is present
  ansible.builtin.lineinfile:
    path: /etc/hosts
    line: '192.168.1.100 app.local'
    state: present

- name: Replace or add line with regexp
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?PermitRootLogin'
    line: 'PermitRootLogin no'
    state: present
    backup: true
  notify: Restart sshd

- name: Remove line
  ansible.builtin.lineinfile:
    path: /etc/hosts
    regexp: '.*old-server.*'
    state: absent

ansible.builtin.blockinfile

- name: Add block of text
  ansible.builtin.blockinfile:
    path: /etc/hosts
    block: |
      192.168.1.10 web1.local
      192.168.1.11 web2.local
      192.168.1.20 db1.local
    marker: "# {mark} ANSIBLE MANAGED BLOCK - SERVERS"
    backup: true

Service Management

ansible.builtin.service

- name: Ensure service is running
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

- name: Restart service
  ansible.builtin.service:
    name: nginx
    state: restarted

- name: Stop and disable service
  ansible.builtin.service:
    name: apache2
    state: stopped
    enabled: false

ansible.builtin.systemd

- name: Reload systemd daemon
  ansible.builtin.systemd:
    daemon_reload: true

- name: Start and enable service
  ansible.builtin.systemd:
    name: myapp
    state: started
    enabled: true
    daemon_reload: true

- name: Mask service
  ansible.builtin.systemd:
    name: apache2
    masked: true

User and Group Management

ansible.builtin.user

- name: Create user
  ansible.builtin.user:
    name: appuser
    uid: 1500
    group: appgroup
    groups: docker,sudo
    shell: /bin/bash
    home: /home/appuser
    createhome: true
    state: present

- name: Set user password
  ansible.builtin.user:
    name: appuser
    password: "{{ user_password | password_hash('sha512') }}"
    update_password: always

- name: Add SSH key
  ansible.builtin.user:
    name: appuser
    ssh_key_bits: 4096
    ssh_key_file: .ssh/id_rsa

ansible.builtin.group

- name: Create group
  ansible.builtin.group:
    name: appgroup
    gid: 1500
    state: present

ansible.builtin.authorized_key

- name: Add SSH authorized key
  ansible.builtin.authorized_key:
    user: appuser
    state: present
    key: "{{ lookup('file', '/home/user/.ssh/id_rsa.pub') }}"

- name: Add multiple keys
  ansible.builtin.authorized_key:
    user: appuser
    state: present
    key: "{{ item }}"
  loop:
    - ssh-rsa AAAAB3... user1@host
    - ssh-rsa AAAAB3... user2@host

Command Execution

ansible.builtin.command

- name: Run command (no shell processing)
  ansible.builtin.command: /usr/bin/make install
  args:
    chdir: /opt/app
    creates: /opt/app/bin/app
  register: make_result
  changed_when: make_result.rc == 0

- name: Run with environment variables
  ansible.builtin.command: /opt/app/deploy.sh
  environment:
    APP_ENV: production
    DB_HOST: localhost

ansible.builtin.shell

- name: Run shell command (with pipes/redirects)
  ansible.builtin.shell: cat /var/log/app.log | grep ERROR > /tmp/errors.txt
  args:
    executable: /bin/bash
  changed_when: false

- name: Use shell with creates
  ansible.builtin.shell: /opt/install.sh
  args:
    creates: /opt/app/installed.flag

ansible.builtin.script

- name: Run script from control node
  ansible.builtin.script: scripts/setup.sh
  args:
    creates: /etc/app/setup.done

Git Operations

ansible.builtin.git

- name: Clone repository
  ansible.builtin.git:
    repo: https://github.com/user/repo.git
    dest: /opt/app
    version: main
    force: true

- name: Clone specific branch/tag
  ansible.builtin.git:
    repo: https://github.com/user/repo.git
    dest: /opt/app
    version: v1.2.3

- name: Clone with SSH key
  ansible.builtin.git:
    repo: git@github.com:user/repo.git
    dest: /opt/app
    key_file: /home/deploy/.ssh/id_rsa
    accept_hostkey: true

Archive Operations

ansible.builtin.unarchive

- name: Extract archive from control node
  ansible.builtin.unarchive:
    src: files/app.tar.gz
    dest: /opt/
    owner: appuser
    group: appgroup

- name: Extract remote archive
  ansible.builtin.unarchive:
    src: /tmp/app.tar.gz
    dest: /opt/
    remote_src: true

- name: Download and extract
  ansible.builtin.unarchive:
    src: https://example.com/app.tar.gz
    dest: /opt/
    remote_src: true

ansible.builtin.archive

- name: Create archive
  ansible.builtin.archive:
    path:
      - /opt/app/config
      - /opt/app/data
    dest: /tmp/backup.tar.gz
    format: gz

Download Operations

ansible.builtin.get_url

- name: Download file
  ansible.builtin.get_url:
    url: https://example.com/file.tar.gz
    dest: /tmp/file.tar.gz
    mode: '0644'
    checksum: sha256:abc123...

- name: Download with authentication
  ansible.builtin.get_url:
    url: https://secure.example.com/file.tar.gz
    dest: /tmp/file.tar.gz
    url_username: user
    url_password: "{{ download_password }}"

URI/API Operations

ansible.builtin.uri

- name: Check API endpoint
  ansible.builtin.uri:
    url: http://localhost:8080/health
    method: GET
    status_code: 200
  register: health_check
  until: health_check.status == 200
  retries: 5
  delay: 10

- name: POST to API
  ansible.builtin.uri:
    url: https://api.example.com/deploy
    method: POST
    body_format: json
    body:
      version: "1.2.3"
      environment: production
    headers:
      Authorization: "Bearer {{ api_token }}"
    status_code: [200, 201]

- name: Download response to file
  ansible.builtin.uri:
    url: https://api.example.com/data
    method: GET
    dest: /tmp/data.json

Cron Jobs

ansible.builtin.cron

- name: Add cron job
  ansible.builtin.cron:
    name: "Daily backup"
    minute: "0"
    hour: "2"
    job: "/opt/backup.sh"
    user: root
    state: present

- name: Add cron job with special time
  ansible.builtin.cron:
    name: "Reboot task"
    special_time: reboot
    job: "/opt/startup.sh"

- name: Remove cron job
  ansible.builtin.cron:
    name: "Daily backup"
    state: absent

Debug and Assert

ansible.builtin.debug

- name: Print variable
  ansible.builtin.debug:
    var: ansible_distribution

- name: Print message
  ansible.builtin.debug:
    msg: "Server IP: {{ ansible_default_ipv4.address }}"

- name: Conditional debug
  ansible.builtin.debug:
    msg: "This is a production server"
  when: env == "production"

ansible.builtin.assert

- name: Validate configuration
  ansible.builtin.assert:
    that:
      - ansible_distribution in ['Ubuntu', 'Debian']
      - app_port | int > 0
      - app_port | int < 65536
      - db_password is defined
    fail_msg: "Configuration validation failed"
    success_msg: "Configuration is valid"
    quiet: false

Set Facts

ansible.builtin.set_fact

- name: Set computed fact
  ansible.builtin.set_fact:
    app_full_version: "{{ app_name }}-{{ app_version }}"
    deployment_time: "{{ ansible_date_time.iso8601 }}"

- name: Set fact with conditional
  ansible.builtin.set_fact:
    db_host: "{{ 'localhost' if env == 'dev' else 'db.prod.example.com' }}"

- name: Combine facts
  ansible.builtin.set_fact:
    app_config:
      name: "{{ app_name }}"
      version: "{{ app_version }}"
      port: "{{ app_port }}"

Include and Import

ansible.builtin.include_tasks

- name: Include tasks dynamically
  ansible.builtin.include_tasks: "{{ ansible_os_family }}.yml"

- name: Include with variables
  ansible.builtin.include_tasks: deploy.yml
  vars:
    app_version: "1.2.3"

ansible.builtin.import_tasks

- name: Import tasks statically
  ansible.builtin.import_tasks: common.yml

ansible.builtin.include_vars

- name: Load variables from file
  ansible.builtin.include_vars:
    file: "{{ env }}.yml"

- name: Load all YAML files from directory
  ansible.builtin.include_vars:
    dir: vars/
    extensions:
      - yml
      - yaml

Wait Operations

ansible.builtin.wait_for

- name: Wait for port to be available
  ansible.builtin.wait_for:
    port: 8080
    delay: 5
    timeout: 300
    state: started

- name: Wait for file to exist
  ansible.builtin.wait_for:
    path: /opt/app/ready
    state: present
    timeout: 300

- name: Wait for service to stop
  ansible.builtin.wait_for:
    port: 8080
    state: stopped
    timeout: 60

Error Handling with Block/Rescue/Always

Basic Block with Rescue

- name: Handle errors gracefully
  block:
    - name: Attempt risky operation
      ansible.builtin.command: /opt/risky_script.sh

    - name: This won't run if above fails
      ansible.builtin.debug:
        msg: "Script succeeded"
  rescue:
    - name: Handle failure
      ansible.builtin.debug:
        msg: "Script failed, performing recovery"

    - name: Log error details
      ansible.builtin.copy:
        content: "{{ ansible_failed_result }}"
        dest: /var/log/error.log

Block with Rescue and Always

- name: Deploy with rollback capability
  block:
    - name: Stop application
      ansible.builtin.service:
        name: myapp
        state: stopped

    - name: Deploy new version
      ansible.builtin.copy:
        src: app-v2.jar
        dest: /opt/app/app.jar
        backup: true
      register: deploy_result

    - name: Start application
      ansible.builtin.service:
        name: myapp
        state: started
  rescue:
    - name: Rollback on failure
      ansible.builtin.copy:
        remote_src: true
        src: "{{ deploy_result.backup_file }}"
        dest: /opt/app/app.jar
      when: deploy_result.backup_file is defined

    - name: Start application with old version
      ansible.builtin.service:
        name: myapp
        state: started
  always:
    - name: Verify application is running
      ansible.builtin.wait_for:
        port: 8080
        timeout: 60

Configuration Update with Validation and Backup

- name: Update config with validation
  block:
    - name: Deploy new configuration
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        backup: true
        validate: 'nginx -t -c %s'
      register: config_update

    - name: Reload nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded
  rescue:
    - name: Restore backup on failure
      ansible.builtin.copy:
        remote_src: true
        src: "{{ config_update.backup_file }}"
        dest: /etc/nginx/nginx.conf
      when: config_update.backup_file is defined

    - name: Reload nginx with old config
      ansible.builtin.service:
        name: nginx
        state: reloaded
  always:
    - name: Verify nginx is responding
      ansible.builtin.uri:
        url: http://localhost/health
        status_code: 200

Accessing Error Variables in Rescue

- name: Use error variables
  block:
    - name: Task that might fail
      ansible.builtin.command: /opt/backup.sh
      register: backup_result
  rescue:
    - name: Log failed task name
      ansible.builtin.debug:
        msg: "Failed task: {{ ansible_failed_task.name }}"

    - name: Log error details
      an