RHCE EX294 Practice Questions and Answers: Original Hands-On Tasks With Solutions
Prepare for the RHCE EX294 exam with confidence! Discover real exam questions, tips for setting up a practice lab, discounted exam vouchers, and trusted resources like WebAsha Technologies for guaranteed success. Learn how to ace the Red Hat Certified Engineer exam and boost your career in Linux and DevOps.
Quick answer: Real RHCE EX294 exam questions are confidential, so no honest site can publish them, and using leaked "dumps" breaks Red Hat's agreement and can cost you the certification. EX294 is a hands-on, roughly four-hour exam on Ansible automation. The reliable way to pass is to practise original tasks like the seven below, on your own lab, until you can build and verify them from memory.
Key takeaways
- EX294 is performance-based. You automate real tasks on live systems, so memorised answers do not help, and no "guaranteed" pass exists.
- Red Hat exam content is covered by a non-disclosure agreement. Sharing or using real questions can lead to certification being revoked, so this page uses original practice tasks only.
- The exam covers the Ansible control node, inventories, ad hoc commands, playbooks, variables, conditionals, handlers, templates, roles, collections and Ansible Vault.
- Always verify your own work: run the playbook twice, and the second run should show no changes (idempotence).
- Check Red Hat's current EX294 objectives for the exact RHEL and Ansible version, because they are updated between releases.
Why this page does not list "real exam questions"
Search results for EX294 are full of pages promising "latest real questions and answers" and a "guaranteed pass". Be careful with them. When you sit a Red Hat exam you agree not to disclose its content, and Red Hat can cancel results and revoke certifications for those who use or share leaked material. Dump sites are also frequently wrong, outdated or built on an earlier exam version. Most importantly, EX294 is a practical exam. It asks you to make machines reach a required state, not to pick the right letter.
So this page gives you something more useful: seven original tasks in the style of the objectives, with worked solutions, and a method for checking your work. If you can do these without looking, you can do the exam.
What is EX294 and what does it test?
EX294 is the Red Hat Certified Engineer (RHCE) exam. It tests Linux automation with Ansible on Red Hat Enterprise Linux. It is a hands-on exam of about four hours in which you complete tasks on a control node and managed nodes. Red Hat publishes the objectives on its Training and Certification pages. The objectives are updated between releases, so use the current list. In outline they cover:
- Installing and configuring an Ansible control node, creating inventories and configuration files.
- Configuring managed nodes: SSH keys and privilege escalation.
- Running ad hoc commands and writing scripts around them.
- Creating playbooks: modules, variables, facts, conditionals, loops, error handling and tags.
- Automating standard RHCSA-level administration: packages, services, firewall, storage, users, SELinux, cron.
- Templates, roles, content collections, Ansible Galaxy and Ansible Vault.
Treat RHCSA skills as a prerequisite. If you cannot manage storage or users by hand, you cannot automate them.
Set up a practice lab
You need one control node and at least three managed nodes, all RHEL (virtual machines are fine), with a user called student that has passwordless sudo on the managed nodes. Our examples use control.example.com and node1 to node3. Keep the Ansible documentation and ansible-doc in mind, because in the exam you will rely on ansible-doc -l and ansible-doc module_name to look up options.
Practice task 1: configuration file and inventory
Task: On the control node, as user student, create /home/student/ansible/ansible.cfg that uses the inventory in the same directory, a roles path of /home/student/ansible/roles, remote user student, and privilege escalation with sudo. Create an inventory with group web containing node1 and node2, group db containing node3, and a parent group lab containing both.
# /home/student/ansible/ansible.cfg
[defaults]
inventory = /home/student/ansible/inventory
roles_path = /home/student/ansible/roles
remote_user = student
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
# /home/student/ansible/inventory
[web]
node1.example.com
node2.example.com
[db]
node3.example.com
[lab:children]
web
db
Check: ansible-inventory --graph shows the groups, and ansible all -m ansible.builtin.ping returns pong from every node. If ping fails, test SSH keys and sudo by hand first.
Practice task 2: an ad hoc command in a script
Task: Write an executable script /home/student/ansible/repos.sh that uses an ad hoc command to configure a yum repository on all nodes.
#!/bin/bash
ansible all -m ansible.builtin.yum_repository \
-a "name=ex294_appstream description='Practice AppStream' baseurl=http://repo.example.com/AppStream gpgcheck=no enabled=yes"
Run chmod +x repos.sh and then ./repos.sh. Use ansible-doc ansible.builtin.yum_repository to check which parameters exist, and in a real setting use gpgcheck=yes with the key location. A second run should report ok, not changed.
Practice task 3: web server with firewall and a templated page
Task: On hosts in group web, install httpd, start and enable it, open the http service in the firewall permanently, and deploy an index.html that shows the host's FQDN and IPv4 address.
# /home/student/ansible/webserver.yml
---
- name: Configure web servers
hosts: web
tasks:
- name: Install httpd
ansible.builtin.dnf:
name: httpd
state: present
- name: Start and enable httpd
ansible.builtin.service:
name: httpd
state: started
enabled: true
- name: Open http in the firewall
ansible.posix.firewalld:
service: http
permanent: true
immediate: true
state: enabled
- name: Deploy index page
ansible.builtin.template:
src: index.html.j2
dest: /var/www/html/index.html
owner: root
group: root
mode: "0644"
# /home/student/ansible/index.html.j2
Welcome to {{ ansible_facts['fqdn'] }} at {{ ansible_facts['default_ipv4']['address'] }}
Check: ansible-playbook webserver.yml, then curl http://node1.example.com. Run the playbook a second time: changed=0 means it is idempotent. Common failure: the firewalld module comes from the ansible.posix collection, so make sure it is installed in your environment.
Practice task 4: users with an Ansible Vault password
Task: Create users alice and bob on the web hosts, as members of group wheel, with a password stored in a vault-encrypted file.
ansible-vault create /home/student/ansible/secret.yml
# in the editor, add:
# pw_developer: Sup3rSecret!
# /home/student/ansible/users.yml
---
- name: Create developer users
hosts: web
vars_files:
- secret.yml
vars:
dev_users:
- alice
- bob
tasks:
- name: Create users in wheel
ansible.builtin.user:
name: "{{ item }}"
groups: wheel
append: true
password: "{{ pw_developer | password_hash('sha512', 'ex294salt') }}"
loop: "{{ dev_users }}"
Run it with ansible-playbook users.yml --ask-vault-pass. The fixed salt is a lab shortcut: without one, password_hash generates a new salt on each run, which makes the task report changed every time. Never keep real passwords in plain text, and never reuse a lab password anywhere else.
Practice task 5: storage with error handling
Task: On hosts where a volume group named research exists, create a logical volume data of 1500 MiB. If that size cannot be created, show a message and create one of 800 MiB instead. If the volume group does not exist, print a message and do nothing.
# /home/student/ansible/lv.yml
---
- name: Create logical volume
hosts: all
tasks:
- name: Report when the volume group is missing
ansible.builtin.debug:
msg: "Volume group research does not exist"
when: "'research' not in (ansible_facts['lvm']['vgs'] | default({}))"
- name: Create the data volume
when: "'research' in (ansible_facts['lvm']['vgs'] | default({}))"
block:
- name: Create 1500 MiB volume
community.general.lvol:
vg: research
lv: data
size: 1500
rescue:
- name: Report that 1500 MiB could not be created
ansible.builtin.debug:
msg: "Could not create logical volume of that size"
- name: Create 800 MiB volume instead
community.general.lvol:
vg: research
lv: data
size: 800
This shows the block, rescue and when pattern, which is a common way to express "try this, otherwise do that". Check the result with ansible all -m ansible.builtin.command -a "lvs". Note that facts must be gathered for ansible_facts['lvm'] to exist, which is the default behaviour.
Practice task 6: a role with a handler
Task: Create a role named motd that writes a message of the day from a template and restarts nothing unless the file changes. Apply it to all hosts.
cd /home/student/ansible
ansible-galaxy init roles/motd
# roles/motd/tasks/main.yml
---
- name: Deploy message of the day
ansible.builtin.template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: "0644"
notify: Show motd changed
# roles/motd/handlers/main.yml
---
- name: Show motd changed
ansible.builtin.debug:
msg: "motd updated on {{ inventory_hostname }}"
# roles/motd/templates/motd.j2
This system is managed by Ansible. Host: {{ ansible_facts['hostname'] }}
# motd.yml
---
- name: Apply motd role
hosts: all
roles:
- motd
Handlers run only when a notifying task reports changed, and they run once at the end of the play, even if notified many times. Run the playbook twice and confirm the handler fires only the first time. In the exam you may also be asked to install roles from a requirements file with ansible-galaxy install -r requirements.yml, so practise that too.
Practice task 7: SELinux boolean and a scheduled job
Task: On the web hosts, allow httpd to make network connections persistently, and create a cron job for user alice that runs every day at 02:30 and logs a line to syslog.
---
- name: SELinux and cron
hosts: web
tasks:
- name: Allow httpd network connections
ansible.posix.seboolean:
name: httpd_can_network_connect
state: true
persistent: true
- name: Daily logger job for alice
ansible.builtin.cron:
name: daily logger
user: alice
minute: "30"
hour: "2"
job: "logger 'EX294 practice job'"
This relies on user alice existing, so run task 4 first. Verify with ansible web -m ansible.builtin.command -a "getsebool httpd_can_network_connect" and crontab -l -u alice on a node.
How to check every task before you move on
- Run
ansible-playbook --syntax-check file.yml. - Run the playbook. Read the recap: failures, unreachable and changed counts.
- Run it again. A correct playbook reports
changed=0. - Log in to a node and look at the result with a direct command, not only Ansible's report.
- Reboot a node if the task involves persistence (services, firewall, SELinux, mounts) and confirm it still works. A change that only exists until reboot is a classic cause of lost marks.
Exam-day habits that matter
- Read every task fully before you start, including the file names, paths and variable names it dictates.
- Use
ansible-docto look up module parameters instead of guessing. Learn to find them fast. - Use fully qualified collection names such as
ansible.builtin.dnf, which is clearer and avoids ambiguity. - Keep playbooks small and test each one, rather than writing one giant file.
- Do not spend more than a set amount of time on one task. Move on and return.
- Leave time at the end to re-run everything and confirm the final state.
Common mistakes
- YAML indentation errors. Use spaces, never tabs, and use an editor that shows whitespace.
- Forgetting
becomefor tasks that need root. - Writing
commandorshelltasks where a proper module exists, which breaks idempotence. - Not quoting values that begin with a template, such as
"{{ var }}", or file modes such as"0644". - Skipping the second run and the reboot test.
Next steps
Rebuild all seven tasks from a blank directory within a fixed time, then invent variations of your own. For the exam plan and tips, read how to pass the RHCE EX294 exam and 10 tips to ace the RHCE EX294 exam. For instructor-led training with lab access, see the RHCE EX294 course.
Related reading
Frequently Asked Questions
What's Your Reaction?
Like
0
Dislike
0
Love
0
Funny
0
Wow
0
Sad
0
Angry
0