
This week kicked my ass a bit. I took a timed RHCE practice exam and failed miserably. After 4 hours, I was only on task 6 out of 18. After pushing for another 3 hours, then for the rest of the week..
I started to lose hope.
Sign up free to receive updates on this series!
After giving up twice, rebuilding the lab, smashing my head against a wall, cry-cuddling my dog, then staring blankly at the screen rethinking my life decisions. I decided to keep pressing forward.
What has tripped me up so far?
Follow directions.. #
First off, I did not set up the lab right. I used RHEL version 10 instead of version 8 (Wow David). This did not give me any problems until I got to custom repository tasks that required RHEL 8.
As a side note, my actual exam is for RHEL 9. So I’ll need to find a specific exam for the correct version or modify some tasks to fit with RHEL 9.
I ended up rebuilding my lab on RHEL 8 to match the practice exam. Which only took about 5 minutes. And now I begin anew with a keen eye for details.
Tasks 1-2: Configuration and adhoc commands #
These tasks are all about setting up inventory, ansible.cfg, and access to hosts. There were a few things I needed to search documentation for.
Inventory #
I ended up opening the official inventory page to make sure this was done right.
Bootstrap #
Here is the adhoc script I came up with for task 2.
#!/bin/bash
ansible ansible2 --become-user root -m user -K --ask-become-pass --become -a "name=automation state=present groups=wheel"
ansible ansible3 --become-user root -m user -K --ask-become-pass --become -a "name=automation state=present groups=wheel"
ansible ansible4 --become-user root -m user -K --ask-become-pass --become -a "name=automation state=present groups=wheel"
ansible ansible5 --become-user root -m user -K --ask-become-pass --become -a "name=automation state=present groups=wheel"
ansible all:!localhost -m file -K --ask-become-pass --become --become-user root -a "path=/home/automation/.ssh state=directory mode='0755'"
ansible all:!localhost -m file -K --ask-become-pass --become --become-user root -a "path=/home/automation/.ssh state=directory mode='0755'"
ansible all:!localhost -m lineinfile -K --ask-become-pass --become --become-user root -a "path=/home/automation/.ssh/authorized_keys state=present create=true line='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCucgpRJSz8pNX3MgjAdRLJA3FHmrNconvssiO0sgtC6nvgO4PTcVQYdBTHeATPJkXRTHdn8GKZnDx7fRrI4WqbqztmtYRPk24QZJ2AZUgoBHsYwge+aNFFKfcEdY2D9dIQQQZl8GpmTnlcSzkbB0bAwaG0ezmmSr63V0nPh62ITQ/ipIy7IMJNuKc9pzus/FhTVI6J6RVbe7u6go4PTsyIAYQGqtvmV0c7g4s6tYuriBwQkeQYj38BopxAak9jCrs2rUm5wIwsA4sIpI3zj4/eHXGH19tklVZsuJgpXbV8F+eJVHCwj9sTCMYFasElTfNB6cwcgjV+DbOMLhaa9kDUa8p8xoXshDzK6P0ACd5UD9ZNYbfaD9M0xcHC8YtmPmaHwMrfnbw6ki91Z3AMGSolY4lY8SP7wkgBpwOKZqwOfDBdGCFYd002zeKwpFeSxWUPNpnXfYZ4fGufWAxpMX0i8h0ia91kVIlkzhdEB3sZkG1L80roBFRSKvm8TOGswX0='"
ansible all:!localhost -m lineinfile -K --ask-become-pass --become --become-user root -a "path=/etc/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'"Task 3: File content #
This task was pretty straightforward.
---
- name: motd message for Proxy Servers
become: yes
hosts: proxy
tasks:
- name: Add text to motd proxy servers
lineinfile:
path: /etc/motd
line: "Welcome to HAProxy server"
- name: motd message for web Servers
become: yes
hosts: webservers
tasks:
- name: Add text to motd webserver
lineinfile:
path: /etc/motd
line: "Welcome to Apache server"
- name: motd message for database Servers
become: yes
hosts: database
tasks:
- name: Add text to motd database servers
lineinfile:
path: /etc/motd
line: "Welcome to MySQL server"Task 4: Configure sshd #
Another easy one. Just open up the sshd_config file on the target host to see what to regex.
[automation@ansible-control plays]$ cat sshd.yml
---
- name: configure sshd
become: yes
hosts: all
tasks:
- name: Set banner
lineinfile:
path: /etc/ssh/sshd_config
state: present
line: 'Banner /etc/motd'
notify: restart sshd
- name: Disable X11
lineinfile:
path: /etc/ssh/sshd_config
state: present
regexp: '^#X11Forwarding'
line: 'X11Forwarding no'
notify: restart sshd
- name: Max Auth
lineinfile:
path: /etc/ssh/sshd_config
state: present
regexp: '^#MaxAuthTries'
line: 'MaxAuthTries 3'
notify: restart sshd
handlers:
- name: restart sshd
service:
name: sshd
state: restartedTask 5: Ansible vault #
I added the user password as plain text at first. Then remembered later this needed to be stored as an MD5 hash. Luckily, the ansible-doc user document had a link to directions for generating the hashed password.
Task 6: Users and groups #
This is when I first had to leave official documentation for help. The answer actually existed in the documentation but I didn’t know what I was searching for. In this task, you need a way to match user id’s based on the number that the id begins with.
I spent a full hour on this task before I ran for help..
The regex_search function is how I solved the problem:
[automation@ansible-control plays]$ cat users.yml
---
- name: webserver users
vars_files:
- secret.yml
- /home/automation/plays/vars/user_list.yml
hosts: webservers
become: yes
tasks:
- name: add uid beginning with 1 to webservers
user:
name: "{{ item.username }}"
state: present
groups: "wheel"
uid: "{{ item.uid }}"
password: " {{ user_password }}"
shell: /bin/bash
loop: "{{ users }}"
when: item.uid | string | regex_search('^1')
- name: Make ssh directories
file:
path: /home/{{ item.username }}/.ssh
state: directory
mode: '0755'
loop: "{{ users }}"
when: item.uid | string | regex_search('^1')
- name: add public key
lineinfile:
path: /home/{{ item.username }}/.ssh/authorized_keys
create: true
line: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCucgpRJSz8pNX3MgjAdRLJA3FHmrNconvssiO0sgtC6nvgO4PTcVQYdBTHeATPJkXRTHdn8GKZnDx7fRrI4WqbqztmtYRPk24QZJ2AZUgoBHsYwge+aNFFKfcEdY2D9dIQQQZl8GpmTnlcSzkbB0bAwaG0ezmmSr63V0nPh62ITQ/ipIy7IMJNuKc9pzus/FhTVI6J6RVbe7u6go4PTsyIAYQGqtvmV0c7g4s6tYuriBwQkeQYj38BopxAak9jCrs2rUm5wIwsA4sIpI3zj4/eHXGH19tklVZsuJgpXbV8F+eJVHCwj9sTCMYFasElTfNB6cwcgjV+DbOMLhaa9kDUa8p8xoXshDzK6P0ACd5UD9ZNYbfaD9M0xcHC8YtmPmaHwMrfnbw6ki91Z3AMGSolY4lY8SP7wkgBpwOKZqwOfDBdGCFYd002zeKwpFeSxWUPNpnXfYZ4fGufWAxpMX0i8h0ia91kVIlkzhdEB3sZkG1L80roBFRSKvm8TOGswX0=
state: present
loop: "{{ users }}"
when: item.uid | string | regex_search('^1')
- name: database users
vars_files:
- secret.yml
- /home/automation/plays/vars/user_list.yml
hosts: database
become: yes
tasks:
- name: add uid beginning with 2 to database
user:
name: "{{ item.username }}"
state: present
groups: "wheel"
uid: "{{ item.uid }}"
password: "{{ user_password }}"
shell: /bin/bash
loop: "{{ users }}"
when: item.uid | string | regex_search('^2')
- name: Make ssh directories
file:
path: /home/{{ item.username }}/.ssh
state: directory
mode: '0755'
loop: "{{ users }}"
when: item.uid | string | regex_search('^2')
- name: add public key
lineinfile:
path: /home/{{ item.username }}/.ssh/authorized_keys
create: true
line: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCucgpRJSz8pNX3MgjAdRLJA3FHmrNconvssiO0sgtC6nvgO4PTcVQYdBTHeATPJkXRTHdn8GKZnDx7fRrI4WqbqztmtYRPk24QZJ2AZUgoBHsYwge+aNFFKfcEdY2D9dIQQQZl8GpmTnlcSzkbB0bAwaG0ezmmSr63V0nPh62ITQ/ipIy7IMJNuKc9pzus/FhTVI6J6RVbe7u6go4PTsyIAYQGqtvmV0c7g4s6tYuriBwQkeQYj38BopxAak9jCrs2rUm5wIwsA4sIpI3zj4/eHXGH19tklVZsuJgpXbV8F+eJVHCwj9sTCMYFasElTfNB6cwcgjV+DbOMLhaa9kDUa8p8xoXshDzK6P0ACd5UD9ZNYbfaD9M0xcHC8YtmPmaHwMrfnbw6ki91Z3AMGSolY4lY8SP7wkgBpwOKZqwOfDBdGCFYd002zeKwpFeSxWUPNpnXfYZ4fGufWAxpMX0i8h0ia91kVIlkzhdEB3sZkG1L80roBFRSKvm8TOGswX0=
state: present
loop: "{{ users }}"
when: item.uid | string | regex_search('^2')Task 7: Scheduled tasks #
Another easy one! The cron module documentation is great here.
[automation@ansible-control plays]$ cat regular_tasks.yml
---
- name: cron for proxy servers
hosts: proxy
become: yes
tasks:
- name: append date to log
cron:
name: "time"
minute: 0
job: "date >> /var/log/time.log"
user: rootTask 8: Software repositories #
This task is dated and later tasks will fail because of it. This shouldn’t be a problem during the actual exam. Just follow examples in ansible-doc yum_repository.
Ended up with this:
[automation@ansible-control plays]$ cat repository.yml
---
- name: software repositories
hosts: database
become: yes
tasks:
- name: mysql-80 repo
ansible.builtin.yum_repository:
name: mysql80-community
description: "MySQL 8.0 YUM Repo"
baseurl: http://repo.mysql.com/yum/mysql-8.0-community/el/8/x86_64/
gpgkey: http://repo.mysql.com/RPM-GPG-KEY-mysql
gpgcheck: true
state: present
enabled: yesTask 9: Create and work with roles #
This is where using an old practice exam really started to really trip me up. I find roles easy to work with and was flying though this one. But then I got one-error-after-another.
Had to change the Python interpreter version on the target host to get this to work.
Also, the repository information for mysql community is outdated. So I disabled the custom repository and just installed mysql-server.
And this is where I ran out of time for the week..
What now? #
After a full week of working on this practice exam, I only got halfway done. This is painful because I thought I was closer to being ready.
I’ll have to get 7X faster in order to pass. Luckily, I have 33 more study days to do this.
Next week, I will do the second half of the practice exam and continue through reviews and labs.
P.S. If you are studying for RHCE or RHCSA, join our Linux study group on Discord.