Server Management

Server Orchestration with Ansible

Written by Jack Williams Reviewed by George Brown Updated on 22 February 2026

Introduction to Server Orchestration and Ansible

Server orchestration means automating the setup, configuration, and operation of many machines so they behave the same way. Instead of manually logging into each server, orchestration runs tasks across groups of servers in a repeatable way.

Ansible is a popular tool for orchestration. It is agentless (uses SSH or WinRM), uses human-readable YAML files called playbooks, and focuses on idempotent actions (running the same task twice has the same result as running it once). Ansible is useful for provisioning servers, deploying applications, and coordinating multi-step workflows across many machines.

This article explains how Ansible works, how to write reliable playbooks, how to structure projects, and how to use Ansible in CI/CD and secure environments.

Ansible Architecture and Core Concepts

Ansible uses a simple model: a control node runs commands over SSH to managed nodes.

  • Control node: the machine where you run ansible or ansible-playbook.
  • Managed nodes: target servers that receive tasks.
  • Inventory: a list of managed nodes organized in groups.
  • Modules: small programs that perform tasks (install a package, copy a file, manage a service).
  • Playbooks: YAML files describing plays and tasks to run on hosts.
  • Roles: reusable, well-structured collections of tasks, files, templates, and variables.
  • Facts: system information gathered from hosts (like IP, OS) available as variables.
  • Plugins: extend Ansible behavior (connection, callback, lookup, inventory).

Ansible emphasizes idempotence, predictable results, and clear separation between description (playbooks) and execution (modules).

Installing and Configuring Ansible

Install Ansible on the control node. Common ways:

  • On Ubuntu/Debian:
    sudo apt update
    sudo apt install ansible

  • On CentOS/RHEL:
    sudo yum install epel-release
    sudo yum install ansible

  • With pip (gives latest version):
    python3 -m pip install –user ansible

After installing, check the version:
ansible –version

Basic configuration lives in /etc/ansible/ansible.cfg or ~/.ansible.cfg. Useful settings:

  • inventory: default inventory file path
  • remote_user: default SSH user
  • host_key_checking: enable/disable host key checking during SSH
  • retry_files_enabled: disable if you don’t want retry files

Set up key-based SSH access from the control node to managed nodes:
ssh-keygen -t ed25519
ssh-copy-id user@host

For Windows hosts use WinRM with proper configuration.

If you need a web UI or RBAC, consider AWX (open source) or Red Hat Ansible Automation Platform.

Inventory Management and Dynamic Inventories

Inventory tells Ansible which hosts to target and how to group them.

Static inventories can be INI-style:
[web]
web1.example.com
web2.example.com

Or YAML format:
all:
hosts:
web1.example.com:
web2.example.com:
children:
db:
hosts:
db1.example.com:

Group variables live in group_vars/, and host-specific variables live in host_vars/.

Dynamic inventories are scripts or plugins that query cloud providers or services to produce the inventory automatically. Common use cases:

  • AWS EC2: use the aws_ec2 plugin to list instances by tag.
  • GCP and Azure have similar plugins.

Benefits of dynamic inventory:

  • Always up-to-date with cloud resources.
  • Easier to manage large fleets.

Use ansible-inventory –list to inspect the inventory output and debug grouping. Consider inventory caching for performance when inventories are large.

Writing Playbooks and Task Execution Basics

Playbooks are the main way to describe orchestration in Ansible. A simple playbook structure:

  • A play maps a group of hosts to tasks.
  • Tasks call modules and have a name for clarity.
  • Plays can set become: true to run tasks as root.

Example playbook:

  • name: Install Nginx on web servers
    hosts: web
    become: true
    tasks:
    • name: Install nginx package
      apt:
      name: nginx
      state: present
      when: ansible_facts[‘os_family’] == ‘Debian’
    • name: Ensure nginx is running
      service:
      name: nginx
      state: started
      enabled: true

Run playbooks with:
ansible-playbook site.yml

Useful playbook features:

  • tags: run a subset of tasks (ansible-playbook site.yml –tags nginx)
  • check mode: –check to preview changes
  • diff mode: –diff to see changed file differences
  • verbosity: -v, -vvv for more detailed logs

Keep tasks small and named clearly. That helps debugging and reuse.

Modules, Plugins, and Collections

Modules are the workhorses in Ansible. Core modules cover packages, files, services, users, and more. Community and vendor modules live in collections.

Install collections with ansible-galaxy:
ansible-galaxy collection install community.general

Use ansible-doc to read module documentation:
ansible-doc apt

Plugin types you will meet:

  • Connection plugins (ssh, winrm)
  • Callback plugins (format and log output)
  • Lookup plugins (get external data)
  • Inventory plugins (dynamic inventory sources)

If you need behavior not provided, you can write custom modules (Python, or any executable) or custom plugins. Prefer collections to organize and distribute modules and roles.

Roles and Project Structure Best Practices

Roles give structure and make code reusable. A typical role layout:

roles/
common/
tasks/
main.yml
handlers/
main.yml
files/
templates/
defaults/
main.yml
vars/
main.yml
meta/
main.yml

Best practices:

  • Keep roles focused on a single responsibility (e.g., nginx, postgres).
  • Use defaults for low-priority settings, vars for required settings.
  • Use templates for configuration files.
  • Keep playbooks thin: mostly include or call roles.
  • Version roles with tags and maintain a requirements.yml to pin versions.

Example requirements.yml:

  • name: geerlingguy.nginx
    src: geerlingguy.nginx
    version: 3.2.0

Install with:
ansible-galaxy role install -r requirements.yml

Structure projects so new team members can find where tasks, templates, and variables live.

Variables, Facts, and Jinja2 Templating

Variables control behavior in playbooks and roles. Variable sources include:

  • Command line: –extra-vars “env=prod”
  • Inventory (host_vars / group_vars)
  • Role defaults and vars
  • Registered variables from tasks
  • Facts gathered by setup module

Variable precedence matters. When two variables share the same name, Ansible uses a set order; explicit extra-vars have the highest priority.

Facts provide host details (ansible_facts). You can gather minimal facts to save time:
gather_facts: false
or
gather_subset: min

Jinja2 templates let you generate configuration files dynamically. Example template fragment:
server {
listen 80;
server_name {{ inventory_hostname }};
root {{ nginx_root | default(‘/var/www/html’) }};
}

Keep templates simple. Avoid complex logic there — compute values in tasks or templates’ surrounding variables instead. Use filters (like | default, | join, | split) for safe and readable templates.

Handlers, Conditionals, Loops, and Error Handling

Handlers run once per play when notified. Use handlers for service restarts after config changes.

Example:

  • name: Update config
    template:
    src: app.conf.j2
    dest: /etc/app/app.conf
    notify: Restart app

handlers:

  • name: Restart app
    service:
    name: app
    state: restarted

Conditionals use when: to control task execution. Keep conditions readable and tested.

Loops let you repeat tasks:

  • name: Create users
    user:
    name: “{{ item.name }}”
    state: present
    loop:
    • { name: ‘alice’ }
    • { name: ‘bob’ }

Error handling:

  • ignore_errors: true skips failures (use sparingly).
  • failed_when: customize when a task is considered failed.
  • block/rescue/always: handle failures cleanly.

Example:
tasks:

  • block:
    • name: Task that may fail
      command: /bin/false
      rescue:
    • name: Handle failure
      debug:
      msg: “Task failed, taking action”
      always:
    • name: Always run cleanup
      file:
      path: /tmp/lockfile
      state: absent

Use retries with until: for transient failures:
retries: 5
delay: 10
until: result.rc == 0

Orchestration Patterns: Rolling Updates, Blue‑Green, Canary

Orchestration patterns help update systems with minimal impact.

Rolling updates:

  • Update a subset of servers at a time.
  • Use serial or batch size in playbooks:
    serial: 10%
  • Remove a server from load balancer, update it, add it back.

Blue-Green deployments:

  • Maintain two identical environments (blue and green).
  • Deploy to the idle environment, run tests, then switch traffic to it.
  • Use inventory groups or labels to represent environments and change routing in a controlled step.

Canary releases:

  • Deploy to a small subset of users or servers first.
  • Monitor metrics and gradually increase traffic to the new version.
  • Use tags, groups, or dynamic inventory to target canary hosts.

Ansible supports these patterns by controlling host groups, using serial, and adding tasks to integrate with load balancers or service meshes. Keep deployment steps explicit and add health checks between steps.

Integrating Ansible with CI/CD and GitOps Workflows

Ansible fits into CI/CD pipelines and GitOps when used in an automated, testable way.

CI/CD tips:

  • Store playbooks and roles in Git.
  • Lint playbooks with ansible-lint and yamllint in pipeline stages.
  • Test roles with Molecule locally and in CI.
  • Run ansible-playbook in pipelines inside containers to ensure consistent runtime.

Secrets and credentials:

  • Use Ansible Vault to encrypt secrets, and unlock them in CI with secure keys.
  • Prefer external secret managers (HashiCorp Vault, AWS Secrets Manager) and fetch secrets at runtime.

GitOps approach:

  • Treat Git as the single source of truth.
  • Combine Ansible with tools that reconcile repository state to infrastructure.
  • Use AWX/Ansible Automation Platform or containerized runners to apply changes from Git pushes.

Automation in CI/CD should be idempotent, tested, and provide clear logging for audits.

Security, Compliance, Monitoring, and Troubleshooting

Security:

  • Use Ansible Vault for secrets: ansible-vault encrypt vars.yml
  • Limit SSH keys and use bastion hosts where appropriate.
  • Run tasks with least privilege; use become only when needed.
  • Audit playbooks and roles for sensitive operations.

Compliance:

  • Codify compliance checks as playbooks (package versions, config settings).
  • Use tags to run compliance scans separately.
  • Report and store results for audits.

Monitoring and logging:

  • Enable callback plugins to send logs to systems like ELK or Splunk.
  • Capture playbook output and return codes in CI jobs.
  • Monitor Ansible Tower/AWX job history for job trends.

Troubleshooting:

  • Add -vvv to ansible-playbook for detailed debug output.
  • Use ansible -m ping host to check connectivity.
  • Use ansible-inventory –list to verify inventory.
  • Common issues: SSH auth, wrong variables, missing dependencies, or fact differences. Reproduce issues locally with smaller inventories.

Performance tips:

  • Reduce fact gathering when not needed.
  • Use forks in ansible.cfg to run more parallel connections.
  • Break large jobs into smaller plays if necessary.

Keep diagnostics simple and reproducible. Log actionable details such as failing hosts, task names, and captured stderr/stdout.

Closing note

Ansible lets you describe server orchestration in clear, repeatable playbooks. Start small, use roles for reuse, test with Molecule, and secure secrets with Vault. With these practices, you can automate deployments, scale updates safely, and keep systems consistent across environments.

About Jack Williams

Jack Williams is a WordPress and server management specialist at Moss.sh, where he helps developers automate their WordPress deployments and streamline server administration for crypto platforms and traditional web projects. With a focus on practical DevOps solutions, he writes guides on zero-downtime deployments, security automation, WordPress performance optimization, and cryptocurrency platform reviews for freelancers, agencies, and startups in the blockchain and fintech space.