community.general
community.general copied to clipboard
doas on Alpine 3.21 fails with "a tty is required"
Summary
When I try to use Ansible with an Alpine 3.21 machine (installed with setup-alpine, which installs doas by default), I get doas: a tty is required in stderr.
use_tty is set to the default true value, and even if I reset it to true explicitly, this still happens.
Issue Type
Bug Report
Component Name
doas
Ansible Version
$ ansible --version
ansible [core 2.18.4]
config file = None
configured module search path = ['/home/spiffyk/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.13/site-packages/ansible
ansible collection location = /home/spiffyk/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.13.2 (main, Feb 5 2025, 08:05:21) [GCC 14.2.1 20250128] (/usr/bin/python)
jinja version = 3.1.5
libyaml = True
Community.general Version
$ ansible-galaxy collection list community.general
# /usr/lib/python3.13/site-packages/ansible_collections
Collection Version
----------------- -------
community.general 10.5.0
Configuration
$ ansible-config dump --only-changed
ANSIBLE_NOCOWS(/home/spiffyk/Projects/<project>/ansible.cfg) = True
ANSIBLE_PIPELINING(/home/spiffyk/Projects/<project>/ansible.cfg) = True
CONFIG_FILE() = /home/spiffyk/Projects/<project>/ansible.cfg
DEFAULT_HOST_LIST(/home/spiffyk/Projects/<project>/ansible.cfg) = ['/home/spiffyk/Projects/<project>/inventory.yaml']
EDITOR(env: EDITOR) = helix
INTERPRETER_PYTHON(/home/spiffyk/Projects/<project>/ansible.cfg) = /usr/bin/python3
GALAXY_SERVERS:
OS / Environment
On my machine: Arch Linux The other machine: Alpine Linux 3.21
Steps to Reproduce
Any playbook with become: true and become_method: community.general.doas paired with an Alpine 3.21 remote with doas will immediately fail during Gathering Facts.
Expected Results
I expected doas to change the user to root properly.
Actual Results
fatal: [ci-test01]: FAILED! =>
ansible_facts: {}
changed: false
failed_modules:
ansible.legacy.setup:
failed: true
module_stderr: |-
doas: a tty is required
module_stdout: ''
msg: |-
MODULE FAILURE: No start of json char found
See stdout/stderr for the exact error
rc: 1
msg: |-
The following modules failed to execute: ansible.legacy.setup
Code of Conduct
- [x] I agree to follow the Ansible Code of Conduct
Files identified in the description:
If these files are incorrect, please update the component name section of the description or use the !component bot command.
cc @JoergFiedler @MacLemon @bcoca @dch @eest @jasperla @mekanix @opoplawski @overhacked @tuxillo click here for bot help
can you supply a full reproducer? Where/how are you setting use_tty? Also provide -vvv output of the failure
https://github.com/Spiffyk/ansible-repro
This minimal repo reproduces the problem. A -vvvv log (with IPs redacted) is in log.txt. The remote is a virtual machine - should be reproducible locally with a very simple VM.
Note: A workaround is to create a /etc/doas.d/nopass.conf file containing this line on the Alpine machine:
permit nopass :wheel
But that is not ideal, obviously. We do want to keep the extra little bit of security provided by the password prompt.
Thanks for your detailed report @Spiffyk !
pipelining=true appears to be a necessary condition to replicate this.
So disabling pipelining may be another workaround. At one point I thought I had bisected the commit that introduced the issue to https://github.com/ansible/ansible/commit/6d2d476113b3a26e46c9917e213f09494fbc0a13, but now I can't replicate that. Ansible (ansible-core) releases before and after it fail the same way when pipelining=true.
There's a PR for the machinectl become plugin that tries to disable pipelining: #9908. Unfortunately that PR depends on support in ansible-core (https://github.com/ansible/ansible/pull/84878), but that PR isn't looking active.
Hmm, though it looks like https://github.com/ansible/ansible/pull/78111 replaces that PR in ansible/ansible, with a slightly different mechanism (the option is called slightly differently). Have to take a closer look tomorrow or so...
(In any case, this fix will only work with ansible-core 2.19+...)
ansible/ansible#78111 replaces that PR in ansible/ansible, with a slightly different mechanism
Setting a class attribute pipelining = False is what I had concluded.
I created a PR for this: #10537. Would be glad if someone could test / review it.