Ansible Automation Fundamentals for Linux Infrastructure

Ansible is a agentless IT automation platform designed for configuration management, application deployment, infrastructure provisioning, and orchestration of complex workflows—such as rolling updates or zero-downtime deployments. It scales seamlessly from small environments with a handful of servers to large-scale enterprise infrastructures spanning thousands of nodes.

Its core strengths lie in three pillars:

  • Simplicity: Minimal learning curve; uses human-readable YAML and requires no client-side daemons or agents.
  • Power: Enables full lifecycle automation—from bootstrapping to decommissioning—with idempotent, repeatable operations.
  • Security & Predictability: Operates over SSH using standard authentication mechanisms (passwords or key pairs), ensuring auditability and deterministic outcomes.

Initial Setup

Install Ansible on the control node via package manager:

yum install -y ansible

Post-installation, the default configuration resides in /etc/ansible/, containing ansible.cfg and hosts. The inventory file (hosts) defines target systems and logical groupings:

[webservers]
192.168.1.6 ansible_user=webadmin hostname=web1
192.168.1.5 ansible_user=webadmin hostname=web2

[dbservers]
192.168.1.10 ansible_user=dbuser

Custom inventory paths can be specified at runtime: ansible-playbook -i ./production-inventory site.yml.

Connection Methods

Ansible supports two primary connection models:

  1. Password-based SSH: Define credentials inline (not recommended for production):
    192.168.1.5 ansible_user=admin ansible_password='P@ssw0rd'
    Then invoke with -k to prompt for SSH password:
    ansible webservers -m ping -k
  2. SSH Key Authentication: Generate keys on the control node:
    ssh-keygen -t ed25519 -f ~/.ssh/ansible_id -N ""
    Distribute the public key to targets:
    ssh-copy-id -i ~/.ssh/ansible_id.pub admin@192.168.1.5
    Reference the private key in inventory or config:
    ansible_ssh_private_key_file=/home/admin/.ssh/ansible_id

Core Command-Line Options

Flag Purpose
-C / --check Perform a dry-run without making changes
-e "key=value" Inject extra variables at runtime
-u / --user Specify remote user (defaults to currant local user)
-b / --become Elevate privileges (e.g., via sudo)
-K / --ask-become-pass Prompt for privilege escalation password

Ad-Hoc Commands

Execute one-off tasks across inventories:

ansible webservers -m ping
ansible dbservers -m shell -a "df -h && uptime"

The shell module executes arbitrary shell commands, while safer alternatives like command avoid shell interpretation.

Built-in Modules

Modules are Ansible’s execution units. List all available modules:

ansible-doc -l

View usage details for a specific module:

ansible-doc copy

Commonly used modules include:

  • copy: Transfer files with checksum validation
  • file: Manage file attributes, permissions, and state (state=directory, state=absent)
  • yum / dnf: Install/remove RPM packages
  • systemd: Control services (state=started, enabled=yes)
  • unarchive: Extract archives (supports tar, zip, gz)
  • debug: Print variables or diagnostic messages

Playbooks: Declarative Automation

Playbooks define infrastructure-as-code using YAML. A minimal playbook structure:

---
- name: Configure web servers
  hosts: webservers
  gather_facts: false
  become: true
  vars:
    app_port: 8080
  tasks:
    - name: Ensure Nginx is installed
      yum:
        name: nginx
        state: present

    - name: Start and enable Nginx service
      systemd:
        name: nginx
        state: started
        enabled: true

Key directives:

  • hosts: Target host group(s) from inventory
  • become: Enable privilege escalation (equivalent to sudo)
  • gather_facts: Disable automatic fact collection for performance in large environments
  • vars: Inline variable definitions scoped to the play

Variable Management

Variables can be defined at multiple levels:

  • Inventory-level: In hosts or dedicated group_vars/ and host_vars/ directories
    Example: group_vars/webservers.yml:
nginx_version: "1.24.0"
log_level: "warn"
  • Playbook-level: Under vars: or vars_files:
  • Runtime: Via -e "var=value" flag

Reference variables using {{ variable_name }}. To capture task output:

- name: Test connectivity
  ping:
  register: ping_result

- name: Display result
  debug:
    var: ping_result

Control Flow

Tags allow selective execution:

- name: Deploy frontend assets
  copy:
    src: ./dist/
    dest: /var/www/html/
  tags: deploy,frontend

Run only tagged tasks:

ansible-playbook site.yml --tags "deploy"

Conditional execution with when:

- name: Restart Nginx only on CentOS
  systemd:
    name: nginx
    state: restarted
  when: ansible_facts['distribution'] == "CentOS"

Loops simplify repetitive tasks:

- name: Create log directories
  file:
    path: "/var/log/{{ item }}"
    state: directory
    mode: '0755'
  loop:
    - app
    - api
    - cache

Other loop constructs enclude loop: "{{ groups['dbservers'] }}" for dynamic host iteration.

Templates with Jinja2

The template module renders dynamic configuration files using Jinja2 syntax:

- name: Deploy Nginx config
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/conf.d/app.conf

In nginx.conf.j2:

server {
    listen {{ app_port }};
    server_name {{ domain_name | default('localhost') }};
    location / {
        proxy_pass http://backend;
    }
}

Jinja2 filters (e.g., | default) enhance flexibility and safety.

Roles for Reusability

Roles enforce modular, reusable automation logic. Directory layout:

roles/
├── nginx/
│   ├── defaults/
│   ├── files/
│   ├── handlers/
│   ├── meta/
│   ├── tasks/
│   │   └── main.yml
│   ├── templates/
│   └── vars/
└── mysql/
    └── ...

A top-level playbook consumes roles:

---
- name: Deploy web stack
  hosts: webservers
  roles:
    - nginx
    - app-deploy

- name: Provision database layer
  hosts: dbservers
  roles:
    - mysql

This pattern promotes separation of concerns, version control compatibility, and community sharing via Ansible Galaxy.

Tags: Ansible Linux automation YAML ssh

Posted on Tue, 29 Sep 2026 16:29:51 +0000 by Matt Kindig