---
title: "Common Ansible Module Usage Patterns"
description: "- name: Install specific version ansible.builtin.apt: name: nginx=1.18.0-0ubuntu1 state: present"
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/module-patterns
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:31:10.849Z
license: CC-BY-4.0
attribution: "Common Ansible Module Usage Patterns — Claudary (https://claudary.paisolsolutions.com/skills/module-patterns)"
---

# Common Ansible Module Usage Patterns
- name: Install specific version ansible.builtin.apt: name: nginx=1.18.0-0ubuntu1 state: present

## Overview

# Common Ansible Module Usage Patterns

## Core Modules (ansible.builtin)

### Package Management

#### ansible.builtin.package (Universal)
```yaml
- name: Install package (OS-agnostic)
  ansible.builtin.package:
    name: nginx
    state: present
```

#### ansible.builtin.apt (Debian/Ubuntu)
```yaml
- 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
```yaml
# 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)
```yaml
# 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
```yaml
# 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
```yaml
# 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- name: Create group
  ansible.builtin.group:
    name: appgroup
    gid: 1500
    state: present
```

#### ansible.builtin.authorized_key
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- name: Run script from control node
  ansible.builtin.script: scripts/setup.sh
  args:
    creates: /etc/app/setup.done
```

### Git Operations

#### ansible.builtin.git
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- name: Import tasks statically
  ansible.builtin.import_tasks: common.yml
```

#### ansible.builtin.include_vars
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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
```yaml
- 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

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/module-patterns) · https://claudary.paisolsolutions.com
