Introduction
When Ansible runs tasks with become: true, it needs to escalate privileges via sudo. If the remote user requires a password for sudo and Ansible doesn't have it, you get "Missing sudo password" or "Incorrect sudo password" errors. This guide covers all methods to provide the sudo password — or eliminate the need for one.
The Error
fatal: [webserver01]: FAILED! => {"msg": "Missing sudo password"}
fatal: [webserver01]: FAILED! => {"msg": "Incorrect sudo password"}
Quick Fix Options
# Option 1: Prompt for sudo password at runtime
ansible-playbook site.yml --ask-become-pass
# or short form:
ansible-playbook site.yml -K
# Option 2: Set in inventory
# inventory/hosts
[webservers:vars]
ansible_become_pass=MySudoPassword
# Option 3: Use vault (recommended)
ansible-playbook site.yml --become --vault-password-file .vault_pass
Method 1: Command-Line Prompt
# Interactive prompt — simplest for manual runs
ansible-playbook -i inventory site.yml -K
# BECOME password: ********
# Combine with SSH password prompt
ansible-playbook -i inventory site.yml -k -K
# SSH password: ********
# BECOME password: ********
Method 2: Inventory Variables
# inventory/hosts
[webservers]
web01 ansible_host=10.0.1.10
web02 ansible_host=10.0.1.11
[webservers:vars]
ansible_user=deploy
ansible_become=true
ansible_become_pass=MySudoP@ss # ⚠️ Plaintext — not recommended
Method 3: Vault-Encrypted Password (Recommended)
# Create encrypted vars file
ansible-vault create group_vars/all/vault.yml
# group_vars/all/vault.yml (encrypted)
ansible_become_pass: "SecureP@ssw0rd!"
# group_vars/all/main.yml (reference vault var)
ansible_become_pass: "{{ vault_become_pass }}"
# Run with vault
ansible-playbook site.yml --vault-password-file .vault_pass
Per-Host Vault Passwords
# host_vars/web01.yml
ansible_become_pass: "{{ vault_web01_become_pass }}"
# host_vars/db01.yml
ansible_become_pass: "{{ vault_db01_become_pass }}"
Method 4: Passwordless Sudo (Best Practice)
# On the remote host, add to /etc/sudoers.d/ansible:
deploy ALL=(ALL) NOPASSWD: ALL
# Automate it with Ansible (requires initial password):
- name: Configure passwordless sudo for deploy user
ansible.builtin.lineinfile:
path: /etc/sudoers.d/ansible
line: "deploy ALL=(ALL) NOPASSWD: ALL"
create: true
mode: '0440'
validate: "visudo -cf %s"
become: true
Limited Passwordless Sudo
# Only specific commands (more secure):
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/apt-get, /usr/bin/cp
Method 5: ansible.cfg Configuration
# ansible.cfg
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false # Set true to always prompt
[defaults]
# Timeout for privilege escalation prompt
timeout = 30
Playbook-Level Configuration
---
- name: Deploy application
hosts: webservers
become: true
become_method: sudo
become_user: root
vars:
ansible_become_pass: "{{ vault_sudo_pass }}"
tasks:
- name: Install packages
ansible.builtin.apt:
name: nginx
state: present
Per-Task Become
- name: Read file as normal user
ansible.builtin.command: cat /home/deploy/.profile
become: false
- name: Install package as root
ansible.builtin.apt:
name: nginx
state: present
become: true
become_user: root
CI/CD Integration
GitHub Actions
- name: Run playbook
env:
ANSIBLE_BECOME_PASS: ${{ secrets.SUDO_PASSWORD }}
run: |
ansible-playbook -i inventory site.yml \
-e "ansible_become_pass=$ANSIBLE_BECOME_PASS"
Using Environment Variable
# ansible.cfg
[defaults]
# Read become password from environment
# (requires custom plugin or extra_vars)
export ANSIBLE_BECOME_PASS="mysecretpass"
ansible-playbook site.yml -e "ansible_become_pass=${ANSIBLE_BECOME_PASS}"
Alternative Become Methods
# su instead of sudo
become_method: su
# pbrun (PowerBroker)
become_method: pbrun
# doas (OpenBSD)
become_method: doas
# pfexec (Solaris)
become_method: pfexec
# runas (Windows)
become_method: runas
become_user: Administrator
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
Missing sudo password | No password provided, sudo requires one | Use -K, set ansible_become_pass, or configure NOPASSWD |
Incorrect sudo password | Wrong password | Verify password, check user exists on remote |
sudo: a password is required | NOPASSWD not set for this user | Add sudoers entry or provide password |
sudo: user not in sudoers | User lacks sudo access | Add to sudo group or create sudoers entry |
Timeout waiting for privilege escalation | sudo prompt hanging | Check requiretty in sudoers, increase timeout |
sudo: sorry, you must have a tty | requiretty set in sudoers | Add Defaults:deploy !requiretty or use become_flags: '-H -S' |
Fix requiretty
# If sudoers has "Defaults requiretty":
- name: Disable requiretty for ansible user
ansible.builtin.lineinfile:
path: /etc/sudoers.d/ansible
line: "Defaults:deploy !requiretty"
create: true
mode: '0440'
validate: "visudo -cf %s"
Security Best Practices
- Use passwordless NOPASSWD — most secure for automation (no passwords stored anywhere)
- If passwords needed, use Vault — never plaintext in inventory
- Limit NOPASSWD scope — allow only needed commands if possible
- Use dedicated automation user — don't use personal accounts
- Audit sudoers regularly — review what the automation user can do
- Rotate passwords — if using become_pass, rotate via Vault rekey
Conclusion
The best fix is passwordless sudo (NOPASSWD: ALL in sudoers) — no passwords to manage or leak. If that's not possible, store the sudo password in Ansible Vault and reference it via ansible_become_pass. Use -K for one-off manual runs. Never store sudo passwords in plaintext inventory files.