Ansible ansible-pull — Local Playbook Execution from Git
Introduction
ansible-pull inverts the default push model. Instead of a central controller pushing configs to nodes, each node pulls its playbook from a Git repository and runs it locally. This is ideal for workstation setup, auto-scaling instances, edge devices, and any scenario where a central controller is impractical.
Basic Usage
# Pull and run a playbook from Git
ansible-pull -U https://github.com/org/ansible-config.git playbook.yml
# With SSH key authentication
ansible-pull -U git@github.com:org/ansible-config.git playbook.yml
# Specific branch
ansible-pull -U https://github.com/org/ansible-config.git -C production playbook.yml
# Run only if repo has changed
ansible-pull -U https://github.com/org/ansible-config.git --only-if-changed playbook.yml
How It Works
1. ansible-pull runs on the TARGET machine (not controller)
2. Clones/updates the Git repository locally
3. Runs the specified playbook against localhost
4. Optionally schedules itself via cron
┌─────────────────┐ git pull ┌──────────────┐
│ Target Machine │ ◄────────────── │ Git Repo │
│ (runs locally) │ │ (playbooks) │
└─────────────────┘ └──────────────┘
# Set up cron to run ansible-pull every 30 minutes
ansible-pull -U https://github.com/org/ansible-config.git \
-C main \
--only-if-changed \
-i localhost, \
-d /opt/ansible-config \
--sleep 60 \
local.yml
# Add to crontab
crontab -e
# */30 * * * * /usr/bin/ansible-pull -U https://github.com/org/ansible-config.git --only-if-changed -d /opt/ansible-config local.yml >> /var/log/ansible-pull.log 2>&1
Self-Installing Cron
# The playbook installs its own cron job
- name: Set up ansible-pull cron
ansible.builtin.cron:
name: "ansible-pull"
minute: "*/30"
job: >
/usr/bin/ansible-pull
-U {{ repo_url }}
-C {{ branch | default('main') }}
--only-if-changed
-d /opt/ansible-config
local.yml
>> /var/log/ansible-pull.log 2>&1
user: root
Cloud-Init Bootstrap
# cloud-init user-data — bootstrap ansible-pull on first boot
#cloud-config
packages:
- ansible
- git
runcmd:
- ansible-pull -U https://github.com/org/ansible-config.git -C main local.yml
Key Options
Option
Description
-U <url>
Git repository URL (required)
-C <branch>
Checkout specific branch/tag
-d <dir>
Local directory to clone into
--only-if-changed
Only run playbook if repo changed
--sleep <sec>
Random sleep before run (prevents thundering herd)
-i localhost,
Use localhost inventory
--accept-host-key
Accept SSH host key on first connect
-e key=val
Extra variables
--vault-password-file
Path to vault password file
--purge
Delete local repo after run
Hostname-Based Configuration
# Apply different configs based on hostname
---
- name: Base configuration
hosts: localhost
connection: local
become: true
roles:
- common
- security
- name: Web server configuration
hosts: localhost
connection: local
become: true
roles:
- nginx
when: "'web' in ansible_hostname"
- name: Database configuration
hosts: localhost
connection: local
become: true
roles:
- postgresql
when: "'db' in ansible_hostname"
Use --only-if-changed — skip playbook run if Git repo hasn't changed
Add --sleep — random delay prevents all nodes pulling at once
Use local.yml — auto-detected filename, no need to specify
Log everything — redirect to file + logrotate
Bootstrap via cloud-init — first-boot installs Ansible and runs pull
Tag the repo — use -C v1.2.3 for pinned versions in production
Conclusion
ansible-pull is perfect when a central controller doesn't make sense — workstation setup, auto-scaling groups, edge devices, and developer machines. Combined with cron and --only-if-changed, nodes self-configure continuously from a Git repository with zero manual intervention.