Ansible OEL 8 DevOps · OEL 8 · Setup

AnsibleSSH Keys, sudo, and become

How Ansible authenticates to managed nodes, the password-less SSH workflow, and the right way to escalate privilege using become — without leaving sudo passwords in your repo.

Every Ansible task runs in two stages: an SSH login as a regular user (called the connection user), then optionally a privilege escalation via sudo or su to become root or another account. The two steps are configured separately so you can SSH in as deploy but install packages as root.

Control Node your laptop ~/.ssh/id_rsa (private) ansible & Python 3 user: deploy SSH on :22 key-based auth Managed Node db1.example.com ~/.ssh/authorized_keys Python 3 (pre-installed) user: deploy + sudo No agent on remote — Ansible ships modules over SSH and runs them with Python
BASH — generate key pair
# ed25519 is faster and stronger than the default RSA-2048
ssh-keygen -t ed25519 -C "ansible@$(hostname)" -f ~/.ssh/id_ed25519

# leave passphrase empty if you'll run from CI/cron, otherwise set one
# (you'll typically use ssh-agent to unlock it once per session)

ls -l ~/.ssh/id_ed25519*
# id_ed25519       (private — never share)
# id_ed25519.pub   (public  — distribute freely)
⚠ Warning: Never commit the private key (id_ed25519) to git. Add id_* patterns to .gitignore in any repo that contains a ~/.ssh/ mirror. The public key (.pub) is safe to commit and copy around.
BASH — distribute public key
# the easy way: ssh-copy-id (asks for the user's password once)
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.56.11
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.56.12

# the manual way (if ssh-copy-id is not available)
cat ~/.ssh/id_ed25519.pub | ssh deploy@192.168.56.11 \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
   cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# verify password-less login works
ssh deploy@192.168.56.11 hostname
# → db1.example.com   (no password prompt)

Ansible can pass the sudo password through --ask-become-pass, but for unattended runs you'll want a passwordless sudo entry for the deploy user. Add this on each managed node (one time, manually):

BASH — add NOPASSWD sudo for deploy user
# on each managed node, as root:
echo 'deploy ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/deploy
sudo chmod 0440 /etc/sudoers.d/deploy

# validate the file before logging out
sudo visudo -c -f /etc/sudoers.d/deploy
# → /etc/sudoers.d/deploy: parsed OK
⚠ Warning: Granting NOPASSWD: ALL means anyone who can SSH as deploy can also become root. Protect the deploy account: enforce key-only auth, no password login, and restrict ~/.ssh/authorized_keys with from= entries to your control node IP.

become: true tells Ansible to escalate privilege for that task. By default it uses sudo to become root. You can target a different user with become_user:

YAML — using become in a play
---
- name: Configure database servers
  hosts: databases
  remote_user: deploy        # SSH in as deploy
  become: true               # then sudo to root for tasks below
  become_method: sudo        # default — also sudo, su, doas, pbrun, ...
  tasks:
    - name: Install MySQL package
      ansible.builtin.dnf:
        name: mysql-server
        state: present

    - name: Initialise mysql data dir
      ansible.builtin.command: mysqld --initialize-insecure
      become_user: mysql     # this single task runs as the mysql account
      args:
        creates: /var/lib/mysql/ibdata1

You can also override become at the task level:

YAML — task-level become override
---
- name: Run two tasks with different escalation
  hosts: webservers
  remote_user: deploy
  tasks:
    - name: Read user's own files (no escalation needed)
      ansible.builtin.command: cat ~/notes.txt
      # become defaults to false — runs as deploy

    - name: Restart nginx (root needed)
      ansible.builtin.systemd:
        name: nginx
        state: restarted
      become: true           # this single task escalates
BASH — verify the full chain
# inventory file
cat > hosts.ini <<EOF
[databases]
192.168.56.11
192.168.56.12

[databases:vars]
ansible_user=deploy
EOF

# ping (tests SSH only)
ansible -i hosts.ini databases -m ansible.builtin.ping

# whoami without become — should report 'deploy'
ansible -i hosts.ini databases -m ansible.builtin.command -a "whoami"

# whoami with become — should report 'root'
ansible -i hosts.ini databases -m ansible.builtin.command -a "whoami" --become
✅ Tip: If the last command prints root for every host, your auth chain is correct. From here on, every playbook in this series will assume key-based SSH + passwordless sudo.