Loading...

Lab 100: Agent-Based Configuration with ansible-pull

Configure a host to pull and apply its desired state from a Git repository using ansible-pull. Run a local self-apply, then schedule it so the node continuously converges without a central controller.

ansible ansible-pull git cron desired-state

Scenario

You want Linux systems to self-configure by pulling their desired state from a Git repository and applying it locally. This is useful when hosts can reach Git but a central controller cannot reliably reach them, such as branch networks, NAT, or pull-only environments with limited inbound access.

Operator context

With ansible-pull, the node becomes the controller. It clones or updates a repo, runs a playbook against localhost, and repeats on a schedule so it stays converged.

Objective

  • Install Ansible and Git on the managed node.
  • Inspect a repo-hosted playbook intended for localhost configuration.
  • Run ansible-pull to apply configuration locally.
  • Schedule ansible-pull to run every 30 minutes.
  • Prepare a log path to capture scheduled run output.

Concepts

  • Push vs pull: central controllers push changes, while ansible-pull lets the node pull its desired state.
  • Desired state: the repo is the source of truth and each run converges toward that configuration.
  • Local targeting: hosts: localhost is the standard pattern for self-application.
  • Scheduling: repeated runs close drift, but you need safe execution patterns to avoid overlaps.
  • Operational visibility: logs are non-negotiable for unattended automation.

Walkthrough

Step 1 : Install Ansible and Git.
Command
sudo dnf install ansible git -y
# Debian/Ubuntu:
# sudo apt install ansible git -y
# Arch:
# sudo pacman -S ansible git

Git pulls your desired state, and Ansible applies it locally.

Step 2 : Inspect the repo-hosted playbook (without editing anything yet).
Commands
git clone https://github.com/example/ansible-lab100.git
cd ansible-lab100
ls -la
sed -n '1,200p' site.yml

Look for hosts: localhost and become: true. That is the standard self-apply pattern.

Step 3 : Apply the desired state locally using ansible-pull.
Command
sudo ansible-pull -U https://github.com/example/ansible-lab100.git -i localhost, site.yml

This clones or updates the repo into Ansible’s pull directory and runs the playbook against localhost. On later runs, you should see fewer changes as the system converges.

Why the trailing comma matters

-i localhost, is a one-host inline inventory. Without the comma, Ansible may treat localhost as a path.

Step 4 : Create a log path for unattended runs.
Commands
sudo mkdir -p /var/log/ansible
sudo touch /var/log/ansible/pull.log
sudo chmod 0644 /var/log/ansible/pull.log

Logging is how you prove convergence happened and how you debug failures without guessing.

Step 5 : Schedule ansible-pull every 30 minutes with safer execution.
Command
crontab -e
Cron entry (recommended)
*/30 * * * * flock -n /var/lock/ansible-pull.lock /usr/bin/ansible-pull -U https://github.com/example/ansible-lab100.git -i localhost, site.yml >> /var/log/ansible/pull.log 2>&1

This uses absolute paths, prevents overlap, and captures output so scheduled runs are observable.

Step 6 : Verify that the schedule is in place and validate logs after a run.
Commands
crontab -l
sudo tail -n 50 /var/log/ansible/pull.log

After the first scheduled run, you should see play recap output and a clear success or failure signal.

Ops Notes

  • If you are pulling from a private repo, the standard approaches are deploy keys, a machine identity flow, or a secret manager integration. Keep credentials out of the repo.
  • Cron runs with a minimal environment. Prefer absolute paths and log redirection.
  • For larger setups, consider systemd timers for better observability and control.

Common breakpoints

ansible-pull runs manually but not in cron

Cron may not have the same PATH. Use absolute paths (for example /usr/bin/ansible-pull) and redirect output to a log.

git clone fails in scheduled runs

The node needs network access to the repo and, for private repos, a non-interactive auth method. Avoid prompts in unattended runs.

inventory errors for localhost

Use -i localhost, for an inline one-host inventory. The trailing comma matters.

runs overlap and fight each other

Use flock to prevent overlapping executions when a run takes longer than your schedule interval.

Cleanup checklist

  • Remove the crontab entry if you are done testing.
  • Remove the cloned repo directory in your working path if needed.
  • Optionally remove the log directory if you want a clean slate.
Commands
crontab -e
# delete the ansible-pull line and save

rm -rf ~/ansible-lab100
sudo rm -f /var/lock/ansible-pull.lock
sudo rm -rf /var/log/ansible

Reference

  • ansible-pull -U <repo_url> -i localhost, <playbook> : Clones or updates a repo and applies the playbook locally against localhost.
    • -U <repo_url>: Git repository URL to pull from.
    • -i localhost,: Inline one-host inventory for localhost.
  • crontab -e : Edit the current user crontab.
  • crontab -l : List the current user crontab.
  • flock -n <lockfile> <command> : Prevents overlapping scheduled runs by using a non-blocking lock.
    • -n: Do not wait if lock is held; exit immediately.
  • mkdir -p <dir> : Creates a directory path, including parents if needed.
    • -p: Create parent directories as required.
  • tail -n <lines> <file> : Shows the last N lines of a file for quick log inspection.
    • -n: Number of lines to show.