How to Execute Ansible Tasks as a Specific Non-Root User (With Sudo/NOPASSWD Examples)


2 views

When working with Ansible playbooks, a common requirement is executing certain tasks with different privilege levels than the default remote user. The standard approaches like remote_user or become directives sometimes behave unexpectedly due to SSH and sudo configuration interactions.

The first attempt using remote_user doesn't work because:

- hosts: staging_servers
  tasks:    
    - name: check user
      remote_user: someusername  # This only changes SSH connection user
      shell: whoami

While the second attempt with sudo fails because:

- hosts: staging_servers
  tasks:
    - name: check user
      sudo: yes                  # Deprecated syntax
      sudo_user: someusername    # Requires password escalation
      shell: whoami

For Ansible 2.0+, the correct approach combines become directives:

- hosts: staging_servers
  tasks:
    - name: Execute as specific user
      become: yes
      become_user: someusername
      become_method: sudo
      shell: whoami
      register: whoami_result

    - debug: var=whoami_result.stdout

Your remote server must have proper sudoers configuration. Verify with:

someusername ALL=(ALL) NOPASSWD:ALL

For complex scenarios requiring multiple user switches:

- hosts: webservers
  tasks:
    - name: First task as default user
      shell: whoami

    - name: Second task as service account
      become: yes
      become_user: serviceuser
      command: id -un

    - name: Third task returns to original
      shell: whoami
  • Test sudo manually on target: sudo -u someusername whoami
  • Add -vvv to ansible-playbook for verbose output
  • Check /var/log/secure or /var/log/auth.log for sudo errors

Instead of NOPASSWD:ALL, consider granular permissions:

someusername ALL=(ALL) NOPASSWD:/usr/bin/systemctl restart nginx

When managing multi-user environments with Ansible, you'll often need to execute tasks as different users. The confusion arises when:

- hosts: webservers
  tasks:
    - name: Verify current user
      shell: whoami
      register: current_user
    - debug: var=current_user.stdout

This typically shows your connection user (defined in inventory) rather than your intended target user. Why? Because Ansible's remote execution defaults to the inventory-defined SSH user.

Method 1: Using become directives

The modern replacement for sudo: in Ansible 2+:

- name: Run command as another_user
  command: /path/to/command
  become: yes
  become_user: another_user
  become_method: sudo

Key advantages:

  • Works with any become method (sudo, su, doas)
  • Clear permission hierarchy
  • Supports privilege escalation prompts

Method 2: Per-task remote_user override

For scenarios where you need direct SSH access (not sudo):

- name: Directly execute as deploy_user
  shell: whoami
  remote_user: deploy_user
  vars:
    ansible_ssh_private_key_file: "/path/to/deploy_user_key"

Note: This requires:

  1. Key-based SSH access for the target user
  2. Proper home directory permissions

Method 3: Playbook-level user switching

When entire plays need different users:

- hosts: db_servers
  remote_user: postgres
  become: no
  tasks:
    - name: Verify PostgreSQL user
      command: psql -c "SELECT current_user"

Your sudoers file needs these critical elements:

# CORRECT FORMAT
deploy_user ALL=(ALL:ALL) NOPASSWD: ALL
# NOT
deploy_user ALL=(ALL) NOPASSWD: ALL  # Missing group context

Add this task to verify sudo capabilities:

- name: Test sudo privileges
  command: sudo -l
  register: sudo_test
  changed_when: false
- debug: var=sudo_test.stdout_lines

A complete workflow for deploying as a restricted user:

- hosts: production
  tasks:
    - name: Pull latest code
      git:
        repo: git@github.com:company/repo.git
        dest: /var/www/app
      become: yes
      become_user: deploy_user
      environment:
        GIT_SSH_COMMAND: "ssh -i /home/deploy_user/.ssh/id_ed25519"

    - name: Set proper ownership
      file:
        path: /var/www/app
        owner: www-data
        group: www-data
        recurse: yes
      become: yes
  • Never use NOPASSWD with root access
  • Restrict sudoers entries to specific commands when possible
  • Consider SSH certificate authentication for service accounts