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

MethodPlatformUse Case
sudoLinux, macOSDefault; most common
suLinux, UnixSwitch user with password
doasOpenBSD, LinuxMinimal sudo alternative
pfexecSolaris/IllumosRBAC-based privilege
runasWindowsRun as different Windows user
machinectlLinux (systemd)Escalation in containers
dzdoLinux (Centrify)Centrify DirectAuthorize
pmrunLinux (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

IssueSolution
"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

  1. Use sudo with NOPASSWD — avoid password prompts in automation
  2. Limit sudo scope — restrict to needed commands in sudoers, not ALL
  3. Use become only when needed — don't run everything as root
  4. Store passwords in Vault — never plain text ansible_become_password
  5. Match method to OS — sudo for Linux, doas for OpenBSD, runas for Windows
  6. 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.