Stage 4 · Provision
Dynamic Inventory & Scale
Delegation & Local Actions
delegate_to, run_once, and orchestrating across hosts.
delegate_to
delegate_to runs a task on a different host than the current play target. Use it when a task needs to execute on a specific host — updating a load balancer, running a database query, or calling an API.
---
- name: Configure web servers
hosts: webservers
tasks:
- name: Deploy application
ansible.builtin.package:
name: myapp
state: latest
- name: Update load balancer
ansible.builtin.uri:
url: "http://loadbalancer.example.com/api/backends"
method: POST
body: '{"host": "{{ inventory_hostname }}", "status": "healthy"}'
delegate_to: loadbalancer.example.comThe load balancer task runs on loadbalancer.example.com, not on the web server. The inventory_hostname variable still refers to the web server.
run_once
---
- name: Configure all servers
hosts: webservers
tasks:
# Run only on the first host
- name: Create database schema
ansible.builtin.command: /opt/app/init-db.sh
run_once: true
# Run only on the first host in a group
- name: Generate config
ansible.builtin.template:
src: config.j2
dest: /shared/config.yml
run_once: true
delegate_to: "{{ groups['webservers'][0] }}"run_once executes the task on only one host in the batch. Useful for initialization tasks that should run once, not on every host.
Local Connection
---
- name: Deploy application
hosts: webservers
tasks:
- name: Run database migration locally first
ansible.builtin.command: /opt/app/migrate.sh
delegate_to: localhost
become: no
run_once: true
- name: Deploy to servers
ansible.builtin.git:
repo: https://github.com/app/repo.git
dest: /opt/app
version: "{{ deploy_version }}"
- name: Wait for application startup
ansible.builtin.wait_for:
port: 8080
timeout: 60
- name: Verify deployment
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:8080/health"
delegate_to: localhost
run_once: truedelegate_to localhost runs a task on the control node. Combined with run_once, this lets you orchestrate actions across multiple environments.
Orchestration Patterns
---
- name: Orchestrate database and application
hosts: dbservers
tasks:
- name: Run migration
ansible.builtin.command: /opt/db/migrate.sh
run_once: true
- name: Update web servers
hosts: webservers
serial: 1
tasks:
- name: Deploy code
ansible.builtin.git:
repo: https://github.com/app/repo.git
dest: /opt/app
version: "{{ deploy_version }}"
- name: Restart application
ansible.builtin.service:
name: myapp
state: restarted
- name: Verify
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200This pattern runs the database migration once, then updates web servers one at a time with verification.
Common Use Cases
- Load balancer updates — register/deregister backends during deployments
- DNS updates — modify DNS records from the control node
- Monitoring — create or update monitoring endpoints
- Database operations — run migrations from a central location
- External API calls — trigger webhooks or notifications
When you delegate a task, facts gathered by that task belong to the delegated host. Use delegate_facts: true to associate facts with the original target host instead.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.