Ansible task fails with 'sudo: a terminal is required' when running over SSH without a TTY
Ansible task fails with "sudo: a terminal is required" when running over SSH without a TTY
Your playbook dies halfway through a deploy at the first become: true task. The remote host returns:
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
You now have a partially configured host, a failed CI run, and a rerun that will hit the same task. The ansible sudo a terminal is required failure is usually a transport and privilege-escalation mismatch, not a broken sudoers file.
Why "ansible sudo a terminal is required" appears over SSH
Ansible opens SSH sessions without a pseudo-terminal by default. sudo expects a terminal when it needs to prompt for a password. Without one, sudo cannot read the password and exits before running your command. [link needed]
The same message appears when a command or shell task calls sudo directly and omits -S. In that case Ansible is not managing the password prompt at all. Run the failing play with -vvv and inspect the exact remote command. If the line is /usr/bin/sudo -H -n ..., sudo is being forced non-interactive. If it is plain sudo ..., no stdin flag was passed.
Fix it with this procedure
1. Confirm where sudo is invoked. Run ansible-playbook -vvv ... and read the expanded command. If the task contains command: sudo ..., fix the task first; otherwise change the become configuration.
2. For Ansible-driven escalation, set become: true, become_method: sudo, and become_flags: -S. Use -S -n only when passwordless sudo is expected. -S tells sudo to read the password from stdin. [link needed]
3. Supply the password source: --ask-become-pass, a vaulted ansible_become_password, or an ansible_become_pass variable scoped to the host or group.
4. If you cannot pass a password, add a narrow sudoers rule with NOPASSWD for the automation user or exact commands. Validate with visudo -c.
5. If sudoers sets Defaults requiretty, allocate a TTY for that connection, for example ansible_ssh_common_args: '-tt' on the host or group. Keep it scoped. This is the other valid end of the ansible sudo a terminal is required fix; do not mix it with passwordless rules unless you need both.
6. Re-run one failing task with --start-at-task or a tag before running the whole play. The -vvv sudo line should now contain -S or a TTY should be present.
When NOT to do this
Do not add -tt globally by habit. A TTY can merge stdout and stderr and change line endings, which breaks tasks that parse command output. [link needed]
Do not add blanket NOPASSWD: ALL unless the automation account is already treated as root-equivalent. Prefer command-scoped rules.
Do not set become_flags: -S without a password source. -S still needs bytes on stdin, so pair it with --ask-become-pass, ansible_become_password, or -n for NOPASSWD.
Checklist
- [ ] Reproduced with
-vvvand identified the exact sudo invocation. - [ ] Fixed direct
sudocalls withsudo -Sor passwordless rules. - [ ] Set
become_flagsdeliberately, not by copy-paste. - [ ] Password supplied via prompt or vault, not hardcoded.
- [ ] TTY allocation (
-tt) used only where required. - [ ] Re-ran one failing task, then the full play.