Ansible become_method — sudo, su, doas, runas Privilege Escalation
Introduction
Ansible's become system handles privilege escalation — running tasks as root or another user. While most people use sudo (the default), Ansible supports multiple escalation methods: su, doas (OpenBSD), pfexec (Solaris), runas (Windows), and more. This guide covers when and how to use each method.
Available Methods
| Method | Platform | Use Case |
|---|---|---|
sudo | Linux, macOS | Default; most common |
su | Linux, Unix | Switch user with password |
doas | OpenBSD, Linux | Minimal sudo alternative |
pfexec | Solaris/Illumos | RBAC-based privilege |
runas | Windows | Run as different Windows user |
machinectl | Linux (systemd) | Escalation in containers |
dzdo | Linux (Centrify) | Centrify DirectAuthorize |
pmrun | Linux (Privilege Manager) | BeyondTrust escalation |
Configuration Levels
ansible.cfg (Global)
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
Inventory (Per Host/Group)
# inventory.yml
all:
children:
linux_servers:
vars:
ansible_become: true
ansible_become_method: sudo
ansible_become_user: root
openbsd_servers:
vars:
ansible_become: true
ansible_become_method: doas
ansible_become_user: root
windows_servers:
vars:
ansible_become: true
ansible_become_method: runas
ansible_become_user: Administrator
Play Level
- name: Configure with sudo
hosts: linux_servers
become: true
become_method: sudo
become_user: root
tasks:
- name: Install package
ansible.builtin.package:
name: nginx
state: present
Task Level
- name: Run as specific user
ansible.builtin.command:
cmd: whoami
become: true
become_method: su
become_user: postgres
sudo (Default)
- name: sudo examples
hosts: all
become: true # become_method defaults to sudo
tasks:
- name: Install as root (default)
ansible.builtin.package:
name: nginx
state: present
- name: Run as specific user
ansible.builtin.command:
cmd: psql -c "SELECT version();"
become_user: postgres
- name: Sudo with password
ansible.builtin.package:
name: docker
state: present
# Pass password via --ask-become-pass or ansible_become_password
sudoers Configuration
# /etc/sudoers.d/ansible
# Allow ansible user to run any command without password
ansible_user ALL=(ALL) NOPASSWD: ALL
# Or restrict to specific commands
ansible_user ALL=(ALL) NOPASSWD: /usr/bin/apt-get, /usr/bin/systemctl, /usr/sbin/service
su
- name: su examples
hosts: legacy_servers
tasks:
- name: Switch to root via su
ansible.builtin.command:
cmd: cat /etc/shadow
become: true
become_method: su
become_user: root
# Requires root password (ansible_become_password)
- name: Switch to application user
ansible.builtin.command:
cmd: /opt/app/bin/status
become: true
become_method: su
become_user: appuser
doas (OpenBSD)
- name: OpenBSD with doas
hosts: openbsd_servers
become: true
become_method: doas
tasks:
- name: Install package
community.general.openbsd_pkg:
name: nginx
state: present
- name: Configure firewall
ansible.builtin.template:
src: pf.conf.j2
dest: /etc/pf.conf
notify: Reload pf
# /etc/doas.conf on OpenBSD
permit nopass ansible_user as root
runas (Windows)
- name: Windows runas
hosts: windows_servers
tasks:
- name: Run as Administrator
ansible.windows.win_command:
cmd: whoami
become: true
become_method: runas
become_user: Administrator
vars:
ansible_become_password: "{{ vault_admin_pass }}"
- name: Install as SYSTEM
ansible.windows.win_package:
path: C:\installers\app.msi
state: present
become: true
become_method: runas
become_user: SYSTEM
Mixed Environments
# group_vars/all.yml
ansible_become: true
# group_vars/linux.yml
ansible_become_method: sudo
# group_vars/openbsd.yml
ansible_become_method: doas
# group_vars/windows.yml
ansible_become_method: runas
ansible_become_user: Administrator
ansible_become_password: "{{ vault_windows_admin_pass }}"
# group_vars/solaris.yml
ansible_become_method: pfexec
Passing Become Passwords
# Interactive prompt
ansible-playbook site.yml --ask-become-pass
# From vault
ansible-playbook site.yml -e "ansible_become_password={{ vault_become_pass }}"
# Per-host in inventory (encrypted with vault)
# host_vars/legacy-server.yml (encrypted with ansible-vault)
ansible_become_password: "root-password-here"
Troubleshooting
| Issue | Solution |
|---|---|
| "sudo: a password is required" | Add NOPASSWD to sudoers or use --ask-become-pass |
| "sudo: no tty present" | Add Defaults !requiretty to sudoers or enable pipelining |
| "su: Authentication failure" | ansible_become_password is wrong or missing |
| "doas: not installed" | Install doas: pkg_add doas (OpenBSD) or apt install doas |
| Windows "Access denied" | Check become_user has admin rights; use correct password |
| "Failed to set permissions" | Target user can't access temp directory; set ansible_remote_tmp |
Best Practices
- Use
sudowithNOPASSWD— avoid password prompts in automation - Limit sudo scope — restrict to needed commands in sudoers, not
ALL - Use
becomeonly when needed — don't run everything as root - Store passwords in Vault — never plain text
ansible_become_password - Match method to OS —
sudofor Linux,doasfor OpenBSD,runasfor Windows - Test with
--check— verify become works before making changes
Conclusion
become_method lets Ansible escalate privileges across any platform — Linux sudo, OpenBSD doas, Windows runas, Solaris pfexec. Set it globally in ansible.cfg for homogeneous environments, or per-group in inventory for mixed fleets. The key is choosing the right method for each platform and configuring passwordless escalation for reliable automation.