Introduction
Ansible's become feature handles privilege escalation — running tasks as root or another user when your connection user lacks the required permissions. It replaces the deprecated sudo: directive with a flexible, pluggable system supporting sudo, su, doas, pfexec, runas (Windows), and network enable mode. This article covers every become directive, practical examples, password handling, security best practices, and troubleshooting.
Quick Start
---
- name: Install and start nginx
hosts: webservers
become: true # Escalate to root for all tasks
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
Run with:
ansible-playbook site.yml --ask-become-pass
Become Directives Reference
| Directive | Default | Scope | Description |
|---|---|---|---|
become | false | play, task, block | Enable privilege escalation |
become_user | root | play, task, block | User to escalate to |
become_method | sudo | play, task, block | Escalation method |
become_flags | — | play, task, block | Extra flags for the method |
become_exe | — | play, task, block | Path to the escalation binary |
Command-Line Equivalents
| CLI Flag | Directive | Description |
|---|---|---|
-b / --become | become: true | Enable become |
-K / --ask-become-pass | — | Prompt for become password |
--become-user USER | become_user | Set become user |
--become-method METHOD | become_method | Set become method |
Connection Variables
# inventory
[webservers]
web01 ansible_become=true ansible_become_user=root
web02 ansible_become_method=su ansible_become_pass={{ vault_su_pass }}
| Variable | Description |
|---|---|
ansible_become | Enable become for host |
ansible_become_user | Become user |
ansible_become_method | Become method |
ansible_become_pass | Become password |
ansible_become_flags | Extra flags |
ansible_become_exe | Path to binary |
Practical Examples
Run as Root (Default)
- name: Manage system service
ansible.builtin.service:
name: httpd
state: started
become: true
# become_user defaults to root
Run as Specific User
- name: Run application as app user
ansible.builtin.command: /opt/myapp/start.sh
become: true
become_user: appuser
Run as Nobody (nologin Shell)
- name: Run as nobody user
ansible.builtin.command: /opt/check-permissions.sh
become: true
become_method: su
become_user: nobody
become_flags: '-s /bin/sh'
Different Methods Per Task
---
- name: Mixed privilege escalation
hosts: servers
tasks:
- name: Install package (sudo to root)
ansible.builtin.apt:
name: nginx
state: present
become: true
become_method: sudo
- name: Configure app (su to appuser)
ansible.builtin.template:
src: app.conf.j2
dest: /opt/app/config.yml
owner: appuser
mode: '0640'
become: true
become_method: su
become_user: appuser
Play-Level vs Task-Level
---
# Play-level: ALL tasks run as root
- name: System setup
hosts: servers
become: true
tasks:
- name: Install packages
ansible.builtin.apt:
name: [nginx, postgresql, redis]
state: present
- name: Create app user
ansible.builtin.user:
name: myapp
system: true
# Override: this task runs as myapp, not root
- name: Initialize application
ansible.builtin.command: /opt/myapp/init.sh
become_user: myapp
Block-Level Become
- name: Application deployment
hosts: appservers
tasks:
- name: System tasks (no become needed)
ansible.builtin.debug:
msg: "Running as connection user"
- name: Root tasks
become: true
block:
- name: Install dependencies
ansible.builtin.apt:
name: [python3, python3-pip]
state: present
- name: Create directories
ansible.builtin.file:
path: /opt/myapp
state: directory
owner: appuser
mode: '0755'
- name: App tasks
become: true
become_user: appuser
block:
- name: Deploy code
ansible.builtin.git:
repo: https://github.com/example/app.git
dest: /opt/myapp/current
- name: Install Python deps
ansible.builtin.pip:
requirements: /opt/myapp/current/requirements.txt
virtualenv: /opt/myapp/venv
Become Methods
| Method | Binary | Platform | Description |
|---|---|---|---|
sudo | /usr/bin/sudo | Linux/macOS | Default, most common |
su | /usr/bin/su | Linux/macOS | Switch user |
doas | /usr/bin/doas | OpenBSD/Linux | Simpler sudo alternative |
pfexec | /usr/bin/pfexec | Solaris | Profile-based execution |
runas | — | Windows | Run as different Windows user |
enable | — | Network | Network device enable mode |
machinectl | /usr/bin/machinectl | Linux | systemd-nspawn containers |
Configure Default Method
# ansible.cfg
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
Password Handling
Interactive Prompt
ansible-playbook site.yml -K
# or
ansible-playbook site.yml --ask-become-pass
Vault-Encrypted Password
# group_vars/all/vault.yml (encrypted with ansible-vault)
vault_become_pass: "s3cret_sudo_p@ss"
# group_vars/all/vars.yml
ansible_become_pass: "{{ vault_become_pass }}"
Per-Host Passwords
# host_vars/web01.yml
ansible_become_pass: "{{ vault_web01_pass }}"
# host_vars/db01.yml
ansible_become_method: su
ansible_become_pass: "{{ vault_db01_su_pass }}"
Passwordless Sudo (Recommended)
Configure sudoers on target hosts:
# /etc/sudoers.d/ansible
ansible ALL=(ALL) NOPASSWD: ALL
# No password needed
- hosts: all
become: true
tasks:
- ansible.builtin.ping:
Network Automation Enable Mode
---
- name: Configure network devices
hosts: switches
gather_facts: false
connection: ansible.netcommon.network_cli
become: true
become_method: ansible.netcommon.enable
vars:
ansible_become_pass: "{{ vault_enable_password }}"
tasks:
- name: Show running config
cisco.ios.ios_command:
commands:
- show running-config
register: config
- name: Configure interface
cisco.ios.ios_config:
lines:
- description Managed by Ansible
- ip address 10.0.0.1 255.255.255.0
parents: interface GigabitEthernet0/1
Windows runas
---
- name: Windows privilege escalation
hosts: windows
tasks:
- name: Install IIS as Administrator
ansible.windows.win_feature:
name: Web-Server
state: present
become: true
become_method: runas
become_user: Administrator
Precedence Order
When become settings conflict, Ansible uses this precedence (highest first):
- Task-level directives
- Block-level directives
- Play-level directives
- Command-line flags (
-b,--become-user) - Connection variables (
ansible_become*) - ansible.cfg
[privilege_escalation]section - Plugin defaults
Troubleshooting
"Missing sudo password"
fatal: [server]: FAILED! => {"msg": "Missing sudo password"}
Fix: Add -K flag or set ansible_become_pass:
ansible-playbook site.yml -K
"Sorry, user is not allowed to execute"
fatal: [server]: FAILED! => {"msg": "sudo: user not allowed to execute '/bin/sh'"}
Fix: Add user to sudoers:
echo "ansible ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/ansible
"Timeout waiting for privilege escalation prompt"
# ansible.cfg — increase timeout
[defaults]
timeout = 30
Become with Unprivileged Users
When both connection user and become_user are unprivileged, Ansible can't use /tmp for module transfer. Fix:
# ansible.cfg
[defaults]
remote_tmp = /tmp/.ansible-${USER}/tmp
[privilege_escalation]
become_flags = -H -S
Or use pipelining:
[connection]
pipelining = true
Best Practices
- Use passwordless sudo — configure sudoers with
NOPASSWDfor the Ansible user - Vault all passwords — never hardcode
ansible_become_pass - Minimize become scope — use task-level
becomeinstead of play-level when only some tasks need it - Use
no_log: trueon tasks that handle passwords - Prefer
sudooversu— sudo provides better audit logging - Create a dedicated Ansible user — don't use personal accounts
- Restrict sudoers — limit to specific commands if
NOPASSWD: ALLis too broad:
ansible ALL=(ALL) NOPASSWD: /usr/bin/apt-get, /usr/bin/systemctl, /usr/bin/cp
- Test with
--check— dry-run before applying become changes
Related Articles
- Ansible Vault Guide
- Ansible Configuration Guide
- Ansible Windows Automation
- Ansible SSH Key Management
Conclusion
Ansible become handles privilege escalation across Linux (sudo, su, doas), Windows (runas), and network devices (enable mode). Set become: true at the task, block, or play level with become_user and become_method to control exactly how privileges escalate. Use passwordless sudo with a dedicated Ansible user and Vault-encrypted passwords for the most secure and practical setup.