How do I write an Ansible task to run a PHP script as a third user; not the root user and not the connecting user, but the “webserver” user?
The NextCloud administration program occ
, according to the documentation, must be run as the webserver user:
sudo -u www-data php occ
To become a different user for running a command, Ansible provides the become
feature. The Ansible documentation sternly recommends against attempting to run commands as a different, non-root user:
Everything is fine if the module file is executed without using
become
, when thebecome_user
is root, or when the connection to the remote machine is made as root. In these cases Ansible creates the module file with permissions that only allow reading by the user and root, or only allow reading by the unprivileged user being switched to.However, when both the connection user and the
become_user
are unprivileged, the module file is written as the user that Ansible connects as (theremote_user
), but the file needs to be readable by the user Ansible is set to become.
Using become_user
to that user
The connection user has sudo
permission to run commands as the third user:
$ sudo -u www-data whoami
www-data
When I use become_user
on the task, to run the command as that user:
- name: "NextCloud: Instance configuration"
become_user: "{{ web_process_user }}"
command:
cmd: >-
php "{{ apache_nextcloud_dir }}/occ" maintenance:install
--no-interaction
…
UPDATE: um, it works. I don't know what changed, but in trying to reproduce the problem, it stopped.
Using shell
with an explicit sudo
invocation as that user
When I configure the Ansible task with a shell
command:
shell: >-
su '{{ web_process_user }}' --shell '/bin/bash' -c ' \
php "{{ apache_nextcloud_dir }}/occ" …
Ansible complains:
[WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running su
I'd love to do that. Ansible's become
would be a much more graceful way than this shell: su
hack.
But when using become
, the problems described in the Ansible documentation occur: the task module sent across the connection for running that command, fails to get the privilege to create its temporary files.
The Ansible documentation advises to either:
- “use pipelining”: That loses the advantages of the default task-module system.
- “avoid becoming an unprivileged user”: Not an option, because the unprivileged webserver user is required for running this command correctly.
How should I make an Ansible task that runs php "{{ apache_nextcloud_dir }}/occ"
as the unprivileged, third user {{ web_process_user }}
?
UPDATE: the become
functionality appears to work correctly now.
There are two ways I know of to deal with this issue. The first one you are already aware of, but seem to have been scared away from it by the documentation. However, the documentation tells you exactly what you need to do to make it work, so you should go through it carefully if this doesn't succeed the first time.
So you need to do two things:
Set
become_user
to the unprivileged user (here,www-data
). This will cause ansible to sudo to that user instead of root.Configure
sudoers
to allow for yourremote_user
tosudo
towww-data
. For example, if yourremote_user
isansible
:Note that this is probably optional, because it is typical to have already configured sudo to allow the ansible user to sudo to any user, something like:
or by placing it in a group that can already do that.
The second way is to have Ansible connect directly to the remote system as the desired user (here,
www-data
) and not sudo. You do this as follows:Add Ansible's ssh public key to the remote user's
.ssh/authorized_keys
.Set
remote_user=www-data
andbecome=no
for the task, block, playbook, role, etc., that needs to run as this user.