Skip to content

IaC — Ansible

🌱 Seedling — core concepts documented, eigenstack playbooks being added.

What Ansible Does

Ansible configures infrastructure after it exists — installs software, copies files, manages services, sets permissions.

Agentless: connects via SSH. No daemon running on target hosts. Idempotent: running a playbook twice produces the same result as running it once.

Core Components

Component Role
Inventory List of hosts and groups to manage
Playbook "Entry point" — YAML description of what to do where
Task Single unit of work (install package, copy file, run command)
Role Logical grouping of tasks, handlers, vars — reusable module (DRY)
Handler Task triggered by another task via notify (e.g., restart nginx after config change)
Tags Labels on tasks/roles for selective execution
Vars Variables — make playbooks reusable across environments

DRY via Roles

Instead of duplicating Docker installation steps across multiple playbooks:

# roles/docker/tasks/main.yml — defined once
- name: Install Docker dependencies
  apt:
    name: "{{ docker_packages }}"
    state: present

# playbooks/eigenstack.yml — used by reference
- hosts: vps_prod
  roles:
    - docker        # reused
    - traefik       # reused
    - nextcloud     # reused

Basic Commands

# Run full playbook
ansible-playbook -i inventory/hosts.yml playbooks/eigenstack.yml

# Run only tasks tagged 'docker'
ansible-playbook -i inventory/hosts.yml playbooks/eigenstack.yml --tags docker

# Dry run (check mode)
ansible-playbook -i inventory/hosts.yml playbooks/eigenstack.yml --check

# Ad-hoc command (without playbook)
ansible all -i inventory/hosts.yml -m ping

Approaches: Imperative vs Declarative

Ansible supports both: - Declarative (preferred): apt: name=docker state=present — describe desired state - Imperative: command: apt-get install docker — explicit steps, less idempotent

Prefer declarative modules over command/shell tasks — they handle idempotency automatically.