Red Hat Certified Engineer (RHCE) #3: Config Files and Connectivity — ansible.cfg, ssh, become
In #2 Inventory we defined which hosts Ansible would manage. This time we settle how Ansible connects to those hosts and with what privileges it does its work. At the center of that sit the configuration file ansible.cfg, SSH key-based connections, and become, which handles privilege escalation. All three have to be in place before a playbook written on the control node runs the way you intended on the managed node.
ansible.cfg is the switchboard that changes nearly every default behavior of Ansible. Which inventory to use, which user to connect as, how to elevate privileges — all of it lives in this one file. The exam regularly serves up the pattern of placing a dedicated ansible.cfg in each project directory and configuring become alongside it, so let’s memorize the lookup precedence and the key entries exactly.
ansible.cfg lookup precedence #
When Ansible runs, it searches for a config file in a fixed order and uses only the first one it finds. Even if files exist in several places, they are not merged — a higher-precedence file completely masks the rest. The search order is as follows.
| Precedence | Location | Description |
|---|---|---|
| 1 | ANSIBLE_CONFIG environment variable | The file at the path named in the variable |
| 2 | ./ansible.cfg | The current directory where you ran the command |
| 3 | ~/.ansible.cfg | The user’s home directory |
| 4 | /etc/ansible/ansible.cfg | The system-wide default |
The point that ties directly to the exam is that the current directory’s ./ansible.cfg beats both the home and system settings. So if you put a dedicated ansible.cfg in each project directory, the settings you intended always apply while you run commands from that directory. When the exam says “work in this directory,” creating an ansible.cfg there is the textbook move.
You can check which config file is actually in effect with the following command.
ansible --versionThe config file line in the output shows the path of the file that was actually read. If you see a path other than the ansible.cfg you intended, recheck the current directory or the environment variable.
Security note: current-directory config #
For Ansible to read the current directory’s ansible.cfg, that directory must be unwritable by other users. An ansible.cfg in a world-writable directory is ignored for security reasons, and a warning is printed. A project directory you created yourself in the exam is usually fine, but when you work in a shared path it’s safer to check the permissions.
Key ansible.cfg settings #
The config file is an INI structure that lists entries in key = value form under [sections]. The two sections used most often in RHCE are [defaults] and [privilege_escalation].
The [defaults] section #
[defaults] defines the most basic behavior — inventory location, the connecting user, the key-checking policy, and so on.
| Key | Role |
|---|---|
inventory | Path to the inventory file or directory to use |
remote_user | The default user to connect as on the managed node |
host_key_checking | Whether to verify the SSH host key. false skips the first-connection prompt |
roles_path | Path to the directory where roles are found |
ask_pass | Whether to prompt for the SSH password on connection |
forks | Number of hosts to process at once (parallelism) |
Let’s look at each entry a little more closely.
inventory. Setting this value means you always use the same inventory even without the-ioption. Pointing it at the project directory’sinventoryfile keeps commands short.remote_user. In the exam you usually connect as a regular user and then elevate privileges with become, so you specify a working account rather than root.host_key_checking. This blocks the host-key verification prompt that appears the first time you connect to a freshly created managed node, so the playbook doesn’t stall. In production it’s safer to leave it on, but in lab environments it’s commonly set tofalse.roles_path. To have Ansible find the roles covered in #11 Roles in a specific directory inside the project, you set this value.
The [privilege_escalation] section #
[privilege_escalation] defines how you do work with root privileges after connecting as a regular user. All become-related settings gather here.
| Key | Role |
|---|---|
become | Whether to turn privilege escalation on by default (true/false) |
become_method | The escalation method. The default is sudo |
become_user | Which user you become after escalating. The default is root |
become_ask_pass | Whether to prompt for the become password |
- Setting
become = trueruns every task in the playbook with escalated privileges by default. Since most RHCE work — package installs, service management — requires root, this value is often left on. become_method. On RHEL you almost always usesudo.become_user. When only a specific task needs to become a different account, you set it separately at the task level and usually leave the global default atroot.become_ask_pass. If sudo requires a password, set this totrue, or supply it with the-Koption when running the command.
SSH key-based connections #
Ansible connects to managed nodes over SSH. To run playbooks automatically without typing a password every time, you register the SSH public key on the managed node and set up key-based authentication. This is the first step of building an RHCE environment.
1) Generate a key pair #
If there’s no key pair on the control node, create one first.
ssh-keygenGenerating it with the default paths (~/.ssh/id_rsa, ~/.ssh/id_rsa.pub) and an empty passphrase lets you connect automatically with no further input.
2) Distribute the public key #
Copy the generated public key to each managed node.
ssh-copy-id devops@node1.example.comssh-copy-id automatically appends the public key to the target host’s ~/.ssh/authorized_keys. You enter the password just once at this step, and from then on you connect with the key. If there are several managed nodes, run it the same way on each host.
3) Specify the connecting user #
Which user Ansible connects as is set with remote_user in ansible.cfg, or per host with ansible_user in the inventory.
[webservers]
node1.example.com ansible_user=devops
node2.example.com ansible_user=devopsThe inventory’s ansible_user applies only to that host and takes precedence over remote_user in ansible.cfg. It’s useful when the connecting account differs from host to host.
Escalating privileges with become #
The account you connect with via the key is usually a regular user. Work that needs root privileges — installing packages, restarting services, editing system files — is handled by borrowing sudo privileges with become.
There are three levels at which you can turn become on.
1) Global setting in ansible.cfg #
The become = true in [privilege_escalation] that we saw earlier has the broadest scope. Every playbook and ad-hoc command you run from this directory escalates privileges by default.
2) Setting at the play or task level #
Inside a playbook, you can specify become for an entire play or for an individual task.
- name: Configure the web server
hosts: webservers
become: true
tasks:
- name: Install httpd
ansible.builtin.dnf:
name: httpd
state: present
- name: Check logs as a regular user
ansible.builtin.command: whoami
become: falsePutting become: true on a play escalates privileges for every task in that play, and setting only a specific task to become: false runs that one task as the original account. A per-task become overrides the play setting, so you only specify the tasks that need an exception.
To run a specific task as an account other than root, attach become_user to the task.
- name: Work as the postgres user
ansible.builtin.command: psql -c "SELECT 1"
become: true
become_user: postgres3) Setting via command-line options #
When you want to elevate privileges one-off without touching the config file, use command-line options.
ansible-playbook site.yml --become -K--become(or-b). Turns on privilege escalation for this run only.-K(--ask-become-pass). Prompts once for the sudo password. Needed when the target account’s sudo requires a password.
If the managed node’s sudo is configured with NOPASSWD to work without a password, you don’t even need -K. In exam environments the working account often has passwordless sudo set up in advance, but if not, supply the password with -K or become_ask_pass.
Connection test #
Once you have the config, the keys, and become in place, check that the connection actually works. The ping module is the fastest tool for the job.
ansible all -m pingAnsible’s ping module isn’t ICMP — it’s a module that connects over SSH and even checks that Python works. If every host returns a response like the following, the connection is healthy.
node1.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}To also verify privilege escalation, turn become on and check the current user.
ansible all -m command -a "whoami" --becomeIf every host returns root, become is working correctly. If you get UNREACHABLE, check the SSH key or ansible_user; if you get a sudo-related error, check the become settings or whether -K is needed.
Full project example #
Let’s tie everything we’ve covered into a single project. Placing ansible.cfg and inventory together in the working directory is the exam’s standard form.
Write ansible.cfg as follows.
[defaults]
inventory = ./inventory
remote_user = devops
host_key_checking = false
roles_path = ./roles
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = falseThe inventory in the same directory looks like this.
[webservers]
node1.example.com
node2.example.com
[dbservers]
node3.example.comWhen you run commands from this directory, ./ansible.cfg is applied automatically, so the intended inventory and privilege escalation work exactly as is — without the -i option or --become.
ansible all -m ping
ansible all -m command -a "whoami"If whoami returns root everywhere, it means ansible.cfg’s become = true was applied. Gathering the config and inventory into a single project directory means the same environment is reproduced every time inside that directory.
Exam points #
- Per-project ansible.cfg. The exam usually designates a specific working directory. Creating an
ansible.cfgthere and spelling outinventory,remote_user, and become is the textbook approach../ansible.cfgbeats both the home and system settings. - become settings. Since most RHCE work demands root privileges, the configuration with
become = truein[privilege_escalation]comes up often. If only a specific task needs an exception, adjust it at the task level withbecome: falseorbecome_user. - Connection check. Right after building the environment, check the SSH connection with
ansible all -m pingand privilege escalation withwhoamiplus--become. - Checking the applied config. The habit of confirming with the
config fileline ofansible --versionthat theansible.cfgactually read is the file you intended prevents small mistakes. - host_key_checking. It’s often set to
falseso the host-key prompt on a new managed node doesn’t stall the playbook.
Wrap-up #
What this post locked in:
- ansible.cfg precedence. Searched in the order
ANSIBLE_CONFIGenvironment variable, current directory, home directory,/etc/ansible— only the first file found is applied - Key settings.
[defaults]’sinventory,remote_user,host_key_checking,roles_path, and[privilege_escalation]’sbecome,become_method,become_user,become_ask_pass - SSH key connection. Make a key with
ssh-keygenand distribute it withssh-copy-id; specify the connecting account withremote_useror the inventory’sansible_user - become. Three ways to escalate sudo privileges — globally in ansible.cfg, at the play and task levels, and via command-line
--become -K - Connection test. Check the connection with
ansible all -m pingand privilege escalation withwhoamiplus--become
Next — ad-hoc commands #
Now that connectivity and privileges are in place, let’s run modules on the fly before we write a playbook.
In #4 ad-hoc commands: running modules on the fly, we’ll cover running a module in one line with the ansible command, the modules used most often (command, shell, copy, file, dnf, service), and the feel for putting ad-hoc to work for quick checks and one-off jobs.