Admin

DevOps

Featured

Ansible AWX: Automated Rolling Patching for 500+ Linux Servers

Patch 500+ Linux servers efficiently with Ansible AWX automation. Implement rolling batches for scalable, zero-downtime updates.

By Sujay SinghPublished: June 22, 202614 min read2 views✓ Fact Checked
Ansible AWX: Automated Rolling Patching for 500+ Linux Servers
Ansible AWX: Automated Rolling Patching for 500+ Linux Servers

Overview: Streamlining Linux Patch Management with Ansible AWX

In the landscape of modern IT infrastructure, managing and maintaining a fleet of Linux servers is a ubiquitous challenge. For organizations operating at scale, say with 500 or more Linux servers, the task of regularly applying security patches and operating system updates can quickly become a significant operational overhead. Manual patching is not only time-consuming and prone to human error but also introduces inconsistencies and potential security vulnerabilities due to delayed or missed updates. This is where the power of automation becomes indispensable.

Ansible AWX (the open-source upstream project for Red Hat Ansible Tower) provides a robust, web-based interface for managing Ansible projects, inventories, and credentials, making it an ideal platform for orchestrating complex automation workflows across large environments. When it comes to OS patching, AWX allows us to move beyond simple script execution to a more sophisticated, auditable, and controlled process, particularly by implementing rolling batch updates.

Rolling batch patching is a critical strategy for minimizing downtime and mitigating risk. Instead of updating all 500+ servers simultaneously, which could lead to a massive outage if an issue arises, we update servers in small, manageable groups. This allows for validation of the batch's success before proceeding to the next, ensuring high availability and system stability. This article will delve into a detailed, publication-ready technical guide on leveraging Ansible AWX to automate the patching of 500+ Linux servers using this very rolling batch methodology, transforming a daunting manual task into an efficient, repeatable, and secure automated process.

Prerequisites for AWX-driven Patching

Before we embark on configuring AWX for large-scale patching, several foundational elements must be in place. These prerequisites ensure a smooth and secure automation journey.

  • Ansible AWX Installation: You must have a functional Ansible AWX instance (or Red Hat Ansible Tower) up and running. This guide assumes AWX is accessible via its web interface.
  • Basic Ansible Knowledge: A fundamental understanding of Ansible concepts such as playbooks, roles, tasks, modules, and inventory is essential.
  • Network Connectivity: The AWX server must have network reachability (typically SSH port 22) to all target Linux servers that will be patched.
  • SSH Access: The designated Ansible user (ansible_user) must have passwordless SSH key-based access to all target Linux servers. It is highly recommended to use a dedicated SSH key pair for automation.
  • Sudo Privileges: The ansible_user on the target servers must be configured with sudo privileges to execute package management commands (e.g., yum update, apt upgrade) without requiring a password. This is typically achieved via /etc/sudoers configuration.
  • Source Control Management (SCM): A Git repository (e.g., GitHub, GitLab, Bitbucket, or an internal Git server) is required to store your Ansible playbooks and inventory files. AWX integrates directly with SCM systems to pull automation content.

Let's ensure the ansible_user has passwordless sudo. On a target server, you might configure /etc/sudoers.d/ansible_user:


# /etc/sudoers.d/ansible_user
ansible_automation ALL=(ALL) NOPASSWD: ALL

Replace ansible_automation with your actual ansible_user. This grants the user full sudo access without prompting for a password, which is crucial for automation. Ensure the file permissions are restrictive, typically 0440.

Step-by-Step Implementation: Orchestrating Patching with AWX

1. Prepare Your Ansible Playbook for Patching

The core of our automation is a robust Ansible playbook designed to handle the patching process across different Linux distributions. This playbook needs to be idempotent, handle reboots gracefully, and be flexible enough to be parameterized.

We'll create a playbook named patch_linux_servers.yml. This playbook will:

  • Update the package manager cache.
  • Install all available updates.
  • Check if a reboot is required after patching.
  • Perform a reboot if necessary and wait for the server to come back online.

To handle different distributions (e.g., RHEL/CentOS vs. Debian/Ubuntu), we'll use Ansible facts and conditional logic.


---
- name: Apply OS Patches and Reboot if Necessary
  hosts: all
  become: yes
  gather_facts: yes
  serial: "{{ batch_size | default(10) }}" # Define batch size for rolling updates

  vars:
    reboot_required: false # Default to no reboot unless explicitly set or detected

  tasks:
    - name: Ensure /etc/motd displays patching in progress (optional)
      ansible.builtin.template:
        src: motd_patching_in_progress.j2
        dest: /etc/motd
        owner: root
        group: root
        mode: '0644'
      when: ansible_os_family == 'RedHat' or ansible_os_family == 'Debian'

    - name: Update all packages on RedHat-based systems
      ansible.builtin.yum:
        name: "*"
        state: latest
        update_cache: yes
      when: ansible_os_family == 'RedHat'

    - name: Update all packages on Debian-based systems
      ansible.builtin.apt:
        name: "*"
        state: latest
        update_cache: yes
        autoclean: yes
        autoremove: yes
      when: ansible_os_family == 'Debian'

    - name: Check if reboot is required on RedHat-based systems
      ansible.builtin.command: needs-restarting -r
      register: reboot_check_rhel
      ignore_errors: yes
      changed_when: false # This command does not change system state
      when: ansible_os_family == 'RedHat'

    - name: Set reboot_required for RedHat if command output indicates
      ansible.builtin.set_fact:
        reboot_required: true
      when:
        - ansible_os_family == 'RedHat'
        - reboot_check_rhel.rc == 1 # needs-restarting returns 1 if reboot is needed

    - name: Check if reboot is required on Debian-based systems
      ansible.builtin.stat:
        path: /var/run/reboot-required
      register: reboot_check_debian
      when: ansible_os_family == 'Debian'

    - name: Set reboot_required for Debian if file exists
      ansible.builtin.set_fact:
        reboot_required: true
      when:
        - ansible_os_family == 'Debian'
        - reboot_check_debian.stat.exists

    - name: Reboot server if required
      ansible.builtin.reboot:
        reboot_timeout: 600 # Wait up to 10 minutes for server to come back
      when: reboot_required | bool

    - name: Ensure /etc/motd is clean after patching (optional)
      ansible.builtin.file:
        path: /etc/motd
        state: absent
      when:
        - reboot_required | bool # Only clean if reboot was performed, or if you prefer to clean always
        - ansible_os_family == 'RedHat' or ansible_os_family == 'Debian'

For the optional MOTD (Message of the Day) tasks, you'd need a template file, e.g., motd_patching_in_progress.j2:


*******************************************************************************
**                                                                           **
**          SYSTEM UNDERGOING SCHEDULED MAINTENANCE AND PATCHING             **
**          Please avoid making changes during this window.                  **
**                                                                           **
*******************************************************************************

Note on serial: The serial: "{{ batch_size | default(10) }}" directive is crucial for rolling updates. It tells Ansible to process only batch_size hosts at a time before moving to the next batch. If batch_size is not defined, it defaults to 10. This allows us to control the rate of updates and minimize impact.

Note on needs-restarting: On RHEL/CentOS, the needs-restarting -r command is part of yum-utils and is an excellent way to detect if a reboot is necessary. If it's not installed, you might need an initial task to install it: ansible.builtin.package: name: yum-utils state: present.

2. Organize Your Inventory

For rolling batches, a well-structured inventory is vital. You can group your 500+ servers into smaller, logical batches. This allows you to target specific groups for patching. For instance, you might have groups like web_servers_batch_1, web_servers_batch_2, db_servers_batch_1, etc. For simplicity, we'll use a static inventory.ini for this example, but AWX excels with dynamic inventories (e.g., from AWS EC2, VMware vCenter, OpenStack).

Example inventory.ini:


[web_servers_batch_1]
webserver001.example.com ansible_host=192.168.1.101
webserver002.example.com ansible_host=192.168.1.102
webserver003.example.com ansible_host=192.168.1.103

[web_servers_batch_2]
webserver004.example.com ansible_host=192.168.1.104
webserver005.example.com ansible_host=192.168.1.105
webserver006.example.com ansible_host=192.168.1.106

[db_servers_batch_1]
dbserver001.example.com ansible_host=192.168.1.201
dbserver002.example.com ansible_host=192.168.1.202

[all:vars]
ansible_user=ansible_automation
ansible_become=yes
ansible_become_method=sudo

Place this inventory.ini file alongside your patch_linux_servers.yml in your Git repository.

3. Configure AWX Credentials

AWX securely stores credentials, separating them from your playbooks. We need at least one Machine Credential for SSH access to the target servers and potentially an SCM Credential if your Git repository is private.

Steps in AWX UI:

  1. Navigate to Credentials -> Add.
  2. Machine Credential (SSH Key):
    • Name: Linux Patching SSH Key
    • Organization: Select your organization.
    • Credential Type: Machine
    • Username: ansible_automation (the user configured for SSH access)
    • SSH Private Key: Paste the entire private key (e.g., ~/.ssh/id_rsa content).
  3. SCM Credential (if private Git repo):
    • Name: Gitlab SCM Key
    • Organization: Select your organization.
    • Credential Type: Source Control
    • SCM Type: Git
    • Username: (Optional, if using SSH key)
    • SCM Private Key: Paste your Git SSH private key.

4. Create an AWX Project

An AWX Project links to your SCM repository containing your playbooks and inventory.

Steps in AWX UI:

  1. Navigate to Projects -> Add.
  2. Name: Linux Patching Automation
  3. Organization: Select your organization.
  4. Source Control Type: Git
  5. SCM URL: https://github.com/your-org/ansible-patching.git (or your private Git URL, e.g., git@gitlab.com:your-org/ansible-patching.git)
  6. SCM Credential: Select your Gitlab SCM Key (if applicable).
  7. SCM Branch/Tag/Commit: main (or your preferred branch).
  8. Click Save. Then, click the Sync Project button (rocket icon) to pull the content from Git.

5. Create an AWX Inventory

AWX Inventories define the hosts you want to manage. For our static inventory.ini, we'll create an inventory and link it to an SCM source.

Steps in AWX UI:

  1. Navigate to Inventories -> Add -> Inventory.
  2. Name: Production Linux Servers
  3. Organization: Select your organization.
  4. Click Save.
  5. On the Inventory details page, navigate to Sources -> Add.
  6. Name: Static Inventory from Git
  7. Source: SCM
  8. Project: Select Linux Patching Automation.
  9. Inventory File: inventory.ini (the path to your inventory file within the Git repo).
  10. Click Save. Then, click the Sync Source button to import hosts and groups from inventory.ini.

6. Define the Job Template

The Job Template ties everything together: the playbook, inventory, and credentials. This is where we configure the rolling batch execution.

Steps in AWX UI:

  1. Navigate to Job Templates -> Add.
  2. Name: Patch Linux Servers - Batch 1
  3. Job Type: Run
  4. Inventory: Select Production Linux Servers.
  5. Project: Select Linux Patching Automation.
  6. Playbook: Select patch_linux_servers.yml from the dropdown.
  7. Machine Credential: Select Linux Patching SSH Key.
  8. Forks: 20 (Controls parallelism for individual tasks within a batch, not the batch size itself).
  9. Limit: web_servers_batch_1,db_servers_batch_1 (This is crucial! It restricts the job to only these specific groups defined in your inventory).
  10. Extra Variables: (JSON/YAML format)
    
    ---
    batch_size: 5
    

    This overrides the default serial: 10 in the playbook, allowing us to define a smaller batch size (e.g., 5 servers at a time within the selected inventory groups) for extremely critical systems.

  11. Options: Consider enabling:
    • Enable Fact Caching (improves performance for subsequent runs).
    • Provisioning Callback (if you need dynamic host provisioning).
  12. Click Save.

You would then clone this job template to create Patch Linux Servers - Batch 2, Patch Linux Servers - Batch 3, and so on, simply by changing the Limit field to target the next set of groups (e.g., web_servers_batch_2).

7. Launching and Monitoring the Patching Process

With the job template configured, you are ready to launch the patching process for your first batch.

Steps in AWX UI:

  1. Navigate to Job Templates.
  2. Find Patch Linux Servers - Batch 1 and click the Launch button (rocket icon).
  3. AWX will start the job, display real-time output, and log all actions.
  4. Monitor the job output carefully. Look for any failed tasks or unexpected behavior.
  5. Once Patch Linux Servers - Batch 1 completes successfully, perform post-patch validation on those servers. This might involve manual spot checks, running application health checks, or automated tests.
  6. If Batch 1 is stable, proceed to launch Patch Linux Servers - Batch 2, and so on, until all batches are patched.

AWX provides a comprehensive job history, allowing you to review past runs, see who launched them, what parameters were used, and the full output. This audit trail is invaluable for compliance and troubleshooting.

Security Considerations for AWX Patching

Automating critical tasks like OS patching requires a robust security posture. AWX offers several features to enhance security:

  • Least Privilege:
    • Ansible User: The ansible_automation user on target servers should have the minimum necessary privileges. While NOPASSWD: ALL for sudo is common for automation, consider restricting commands if your environment and compliance allow.
    • AWX RBAC: Implement Role-Based Access Control (RBAC) within AWX. Grant users only the permissions they need (e.g., specific users can launch patching jobs, others can only view). Separate duties for credential management, project creation, and job execution.
  • Credential Management:
    • AWX securely stores SSH private keys and other credentials, encrypting them in its database. Never hardcode credentials in playbooks or clear text files.
    • Use Ansible Vault for any sensitive data (e.g., API keys, database passwords) that might be directly in your playbooks or variable files, even if AWX stores credentials securely. This adds another layer of protection for your SCM.
  • Network Security:
    • Ensure the AWX server's network access to target servers is restricted to necessary ports (SSH - 22).
    • Consider placing AWX in a dedicated, secured subnet.
    • Utilize firewalls (e.g., firewalld, ufw, security groups) on both the AWX server and target servers.
  • Auditability:
    • AWX provides a detailed audit trail of all job executions, including who launched the job, when, what playbook was used, and the full output. This is crucial for compliance and incident response.
    • Integrate AWX logs with a centralized logging system (e.g., Splunk, ELK stack).
  • SCM Security:
    • Protect your Git repository with strong authentication and access controls.
    • Regularly audit changes to playbooks and inventory files.

Best Practices for Robust Patch Automation

To ensure your automated patching process is reliable, efficient, and safe, adhere to these best practices:

  • Test Environment First: Always test your patching playbook and AWX configuration on a non-production, representative staging environment before deploying to production. This helps catch unforeseen issues, especially with new patches.
  • Idempotency: Ensure your Ansible playbooks are idempotent. Running the playbook multiple times should yield the same result without unintended side effects. This is naturally handled by modules like ansible.builtin.package.
  • Source Control All the Things: Keep all your Ansible playbooks, roles, inventory files, and even AWX configurations (if using AWX CLI/API for configuration as code) in a version-controlled Git repository. This enables collaboration, history tracking, and easier rollbacks.
  • Pre- and Post-Patch Health Checks: Incorporate tasks into your playbook or as separate jobs to perform health checks before and after patching. This could involve checking service statuses (systemctl status), application endpoints (curl), or system metrics. If pre-checks fail, halt the patching. If post-checks fail, trigger alerts.
  • Notifications: Configure AWX to send notifications (email, Slack, PagerDuty) on job success, failure, or completion. This keeps relevant teams informed and allows for quick response to issues.
  • Maintenance Windows: Schedule patching during designated maintenance windows, typically during low-traffic periods, even with rolling updates. Communicate these windows to stakeholders. AWX's scheduling feature can automate this.
  • Rollback Strategy: Have a clear rollback strategy. For virtual machines, this might involve taking snapshots before patching. For applications, it could mean reverting to a previous code deployment. While Ansible itself doesn't offer an "undo" button for OS patching, a solid recovery plan is essential.
  • Dynamic Inventory: For highly dynamic environments (e.g., cloud instances that scale up and down), leverage AWX's dynamic inventory features (AWS EC2, Azure RM, Google Compute Engine, VMware vCenter). This ensures your inventory is always up-to-date without manual intervention.
  • Modular Playbooks and Roles: Break down complex playbooks into smaller, reusable roles. For example, a common role for basic system setup, a patching role for the actual update logic, etc. This improves readability, maintainability, and reusability.
  • Parameterization: Use Ansible variables and AWX's Extra Variables to make your playbooks flexible. This allows you to easily change parameters like batch_size, target groups (using Limit), or even enable/disable reboots without modifying the playbook code.

FAQ

Q1: How do I handle different Linux distributions (RHEL/CentOS vs. Ubuntu/Debian) within a single playbook?

A: As demonstrated in the example playbook, you can use Ansible facts, specifically ansible_os_family, to apply conditional logic. Ansible gathers facts about target systems at the beginning of a playbook run. You can then use when: ansible_os_family == 'RedHat' or when: ansible_os_family == 'Debian' to execute distribution-specific tasks (e.g., yum for RedHat-based systems and apt for Debian-based systems). For more complex scenarios, you might use roles, with each role having tasks specific to different OS families within its tasks/ directory, and calling them conditionally.

Q2: What if a server fails to reboot or come back online after patching? How does AWX handle this?

A: Ansible's ansible.builtin.reboot module includes a reboot_timeout parameter (e.g., reboot_timeout: 600) which specifies how long Ansible should wait for the server to become reachable again via SSH after a reboot. If the server doesn't come back online within this timeout, the task will fail, and consequently, the AWX job will fail for that specific host. AWX will then mark the job as 'Failed' (or 'Partially Failed' if other hosts in the batch succeeded). You'll receive notifications (if configured) and can investigate the specific host's console or logs to determine the root cause of the reboot failure.

Q3: Can I automate the entire patching process end-to-end without any manual intervention, including validation?

A: While technically possible, fully automated, end-to-end patching of critical systems without any human oversight is often approached with caution. For highly critical systems, a common pattern involves automating the patching of each batch, followed by automated health checks and then a manual review and approval before proceeding to the next batch. For less critical systems or development environments, you can achieve full automation by integrating comprehensive pre- and post-patch health checks, automated application testing, and robust rollback mechanisms within your AWX workflows. This requires significant upfront investment in test automation and confidence in your system's resilience. Scheduled jobs in AWX can manage the timing, but human intervention points can be built in through job templates that require manual

Written By

Sujay Singh

Technology Expert / Cloud Architect at Virtual Venture covering AI, cloud computing, cybersecurity, and emerging tech trends.

Sources & References

• Official company announcements and press releases

• Industry reports from Gartner, IDC, and Statista

• Peer-reviewed research and technical documentation

• On-record statements from industry experts

Last verified: June 22, 2026

Fact-checked by TechNews Venture editorial team

Leave a Comment

Comments are moderated and will appear after review.