Run single command as root?

A custom command during deploy should be run as root (only this one command!).
become: yes alone doesn’t work as ansible tries to sudo as the deploying web user.

Adding remote_user: "{{ admin_user }}"to the command is
still insufficient because ansible doesn’t know the sudo password.

I had to add the ansible_become_pass with admin password to inventory to make the it finally work.
The admin password is already set in ansible vault though and ideally it should just work out of the box like the separate server playbook for provisioning does with become: true becoming root from admin user.

Any ideas? Why can become: true commands run in server playbook but fail in deploy playbook? Is the remote user forced by the deploy script?

(I’m going to attempt an answer anyone can feel free to correct me. I’m still learning this stuff.)

I think you’ve answered yourself in your the original post:

admin is the user for provisioning and web is the user for deploys. Each user has sufficient privileges for the tasks they need to accomplish. This is good practice as you wouldn’t want your deploy to be capable of screwing up your server configuration. You should feel confident that deploying (or rolling back a deploy) is a safe action.

From what I can tell, the web user does have sudo access to services:

This makes sense because php-fpm is reloaded near the end of the deploy:

So I guess in your case, you should either:

  1. Assess whether this is a task for provisioning instead of deployment.
  2. In the users role, grant web user the limited but sufficient privileges to accomplish the task.

I don’t know how to guide you on that second one, but — unless someone smarter swoops in to give a smart answer — I know from experience that you can learn a lot from just reading through the Ansible roles Trellis has going. That’s where I would start.

3 Likes

I agree with everything @knowler said, also the part about

you can learn a lot from just reading through the Ansible roles Trellis has going

For example, how Trellis loads the sudo password:

Here are some example tasks you could insert in deploy.yml

    - set_fact:
        ansible_become_pass: "{% raw %}{{ (vault_users | selectattr('name', 'equalto', admin_user) | first).password }}{% endraw %}"
      no_log: true

    - command: whoami
      register: whodis
      remote_user: "{{ admin_user }}"
      become: yes

    - debug:
        msg: user is {{ whodis.stdout }}

Output:

user is root

Or, don’t bother with the task automatically loading sudo password, but just invoke ansible-playbook with --ask-become-pass option (or -K for short).

3 Likes

Thanks!
I add the mount and umount commands as allowable sudo commands for user web. This seems to be the least intrusive way.