├── image
└── redhat.png
├── LICENSE
└── README.md
/image/redhat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/soficx/rhce/HEAD/image/redhat.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Ahmed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### :star: RHCE
2 | ---
3 | 
4 | [](https://opensource.org/licenses/MIT "MIT License")
5 | [](https://github.com/soficx/)
6 |
7 | ---
8 | ### Description:
9 |
10 | These are a few practice exams to get ready for the Red Hat Certified Engineer exam
11 | The first practice exam was created by [Lisenet](https://www.lisenet.com/2019/ansible-sample-exam-for-ex294/) . The practice exams cover as many of the exam [objectives](https://www.redhat.com/en/services/training/ex294-red-hat-certified-engineer-rhce-exam-red-hat-enterprise-linux-8?section=Objectives) as possible
12 |
13 | ---
14 | #
15 | ## Contents
16 |
17 | - [RHCE8 Practice Exam 1](#rhce8-practice-exam-1)
18 | - [RHCE8 Practice Exam 2](#rhce8-practice-exam-2)
19 |
20 | ---
21 | ###### ***Requirements*** :
22 | - You will need five RHEL 8 virtual machines to be able to successfully complete all questions.
23 | - One VM will be configured as an Ansible control node.
24 | - Other four VMs will be used to apply playbooks to solve the sample exam questions.
25 |
26 | #### RHCE8 Practice Exam 1
27 |
28 | - ***Task 1 :***
29 | Install ansible package on the control node (including any dependencies) and configure the
30 | following:
31 | - 1 - Create a regular user **automation** with the password of devops. Use this user for all sample
32 | exam tasks.
33 | - 2 - All playbooks and other Ansible configuration that you create for this sample exam should
34 | be stored in /home/automation/plays.
35 | - 3 - Create a configuration file /home/automation/plays/ansible.cfg to meet the following requirements:
36 | - The roles path should include /home/automation/plays/roles, as well as any other path that may be required for the course of the sample exam.
37 | - The inventory file path is /home/automation/plays/inventory.
38 | - Privilege escallation is disabled by default.
39 | - Ansible should be able to manage 10 hosts at a single time.
40 | - Ansible should connect to all managed nodes using the automation user.
41 | - Create an inventory file /home/automation/plays/inventory with the following:
42 | - ansible2.hl.local is a member of the proxy host group.
43 | - ansible3.hl.local is a member of the webservers host group.
44 | - ansible4.hl.local is a member of the webservers host group.
45 | - ansible5.hl.local is a member of the database host group
46 |
47 | [Solution of Task1](#solution-of-task1)
48 |
49 | - ***Task 2 :***
50 | - Generate an SSH key pair on the control node for the automation user. You can perform this step manually.
51 | - Write a script ***/home/automation/plays/adhoc.sh*** that uses Ansible ad-hoc commands to achieve the following:
52 | - User **automation** is created on all inventory hosts.
53 | - The SSH public key that you just generated is copied to all managed hosts for the automation user.
54 | - The automation user has full sudo access on all managed nodes without having to provide a password.
55 |
56 | After running the adhoc.sh bash script, you should be able to SSH into all managed hosts using the automation user without a password, as well as a run all
57 | privileged commands.
58 |
59 | [Solution of Task2](#solution-of-task2)
60 |
61 | - ***Task 3 :***
62 |
63 | - Create a playbook **/home/automation/plays/motd.yml** that runs on all inventory hosts and does the following:
64 | The playbook should replace any existing content of /etc/motd with text. Text depends on the host group.
65 | - On hosts in the proxy host group the line should be “Welcome to HAProxy server”.
66 | - On hosts in the webserver host group the line should be “Welcome to Apache server”.
67 | - On hosts in the database host group the line should be “Welcome to MySQL server”
68 |
69 | [Solution of Task3](#solution-of-task3)
70 |
71 | - ***Task 4 :***
72 |
73 | Create a playbook **/home/automation/plays/sshd.yml** that runs on all inventory hosts and configures SSHD daemon as follows:
74 | 1. banner is set to /etc/motd
75 | 2. X11Forwarding is disabled
76 | 3. MaxAuthTries is set to 3
77 |
78 | [Solution of Task4](#solution-of-task4)
79 |
80 | - ***Task 5 :***
81 | Create Ansible vault file **/home/automation/plays/secret.yml**. Encryption/decryption password is devops.
82 | Add the following variables to the vault:
83 | 1. user_password with value of devops
84 | 2. database_password with value of devops
85 |
86 |
87 | [Solution of Task5](#solution-of-task5)
88 |
89 |
90 | - ***Task 6 :***
91 | You have been provided with the list of users below. Use **/home/automation/plays/vars/user_list.yml** file to save this content.
92 | ```yml
93 | ---
94 | users:
95 | - username: alice
96 | uid: 1201
97 | - username: vincent
98 | uid: 1202
99 | - username: sandy
100 | uid: 2201
101 | - username: patrick
102 | uid: 2202
103 | ```
104 | - Create a playbook **/home/automation/plays/users.yml** that uses the vault file **/home/automation/plays/secret.yml** to achieve the following:
105 | 1. Users whose user ID starts with 1 should be created on servers in the webservers host group.
106 | 2. Users whose user ID starts with 2 should be created on servers in the database host group.
107 | 3. All users should be members of a supplementary group wheel. All users password should be used from the user_password variable
108 | 4. Shell should be set to /bin/bash for all users.
109 | 5. Account passwords should use the SHA512 hash format.
110 | After running the playbook, users should be able to SSH into their respective servers without passwords.
111 |
112 | [Solution of Task6](#solution-of-task6)
113 |
114 |
115 | - ***Task 7 :***
116 | - Create a playbook **/home/automation/plays/regular_tasks.yml** that runs on servers in the proxy host group and does the following:
117 | 1. A root crontab record is created that runs every hour.
118 | 2. The cron job appends the file /var/log/time.log with the output from the date command.
119 |
120 | [Solution of Task7](#solution-of-task7)
121 |
122 | - ***Task 8 :***
123 | Create a playbook **/home/automation/plays/repository.yml** that runs on servers in the database host group and does the following:
124 | 1. A YUM repository file is created.
125 | 2. The name of the repository is mysql56-community.
126 | 3. The description of the repository is “MySQL 5.6 YUM Repo”.
127 | 4. Repository baseurl is http://repo.mysql.com/yum/mysql-5.6-community/el/7/x86_64/.
128 | 5. Repository GPG key is at http://repo.mysql.com/RPM-GPG-KEY-mysql.
129 | 6. Repository GPG check is enabled.
130 | 7. Repository is enabled.
131 |
132 | [Solution of Task8](#solution-of-task8)
133 |
134 | - ***Task 9 :***
135 | Create a role called sample-mysql and store it in **/home/automation/plays/roles**. The role should satisfy the following requirements:
136 | 1. A primary partition number 1 of size 800MB on device /dev/sdb is created.
137 | 2. An LVM volume group called vg_database is created that uses the primary partition created above.
138 | 3. An LVM logical volume called lv_mysql is created of size 512MB in the volume group
139 | vg_database.
140 | 4. An XFS filesystem on the logical volume lv_mysql is created.
141 | 5. Logical volume lv_mysql is permanently mounted on /mnt/mysql_backups.
142 | 6. mysql-community-server package is installed.
143 | 7. Firewall is configured to allow all incoming traffic on MySQL port TCP 3306.
144 | 8. MySQL root user password should be set from the variable database_password (see task
145 | #5).
146 | 9. MySQL server should be started and enabled on boot.
147 | 10.MySQL server configuration file is generated from the my.cnf.j2 Jinja2 template with the following content:
148 | ```txt
149 | [mysqld]
150 | bind_address = {{ ansible_default_ipv4.address }}
151 | skip_name_resolve
152 | datadir=/var/lib/mysql
153 | socket=/var/lib/mysql/mysql.sock
154 | symbolic-links=0
155 | sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
156 | [mysqld_safe]
157 | log-error=/var/log/mysqld.log
158 | pid-file=/var/run/mysqld/mysqld.pid
159 | ```
160 | Create a playbook /home/automation/plays/mysql.yml that uses the role and runs on hosts in the
161 | database host group.
162 | [Solution of Task9](#solution-of-task9)
163 |
164 | - ***Task 10 :***
165 | Use Ansible Galaxy to download and install geerlingguy.haproxy role in **/home/automation/plays/roles**.
166 | Create a playbook **/home/automation/plays/haproxy.yml** that runs on servers in the proxy host group and does the following:
167 | 1. Use geerlingguy.haproxy role to load balance request between hosts in the webservers host group.
168 | 2. Use **roundrobin** load balancing method.
169 | 3. HAProxy backend servers should be configured for HTTP only (port 80).
170 | 4. Firewall is configured to allow all incoming traffic on port TCP 80.
171 | If your playbook works, then doing “curl http://ansible2.hl.local/” should return output from the web server (see task #9 ).
172 | Running the command again should return output from the other web server.
173 |
174 | [Solution of Task10](#solution-of-task10)
175 |
176 |
177 | - ***Task 11 :***
178 | Create a playbook **/home/automation/plays/selinux.yml** that runs on hosts in the webservers host group and does the following:
179 | 1. Uses the selinux RHEL system role.
180 | 2. Enables httpd_can_network_connect SELinux boolean.
181 | 3. The change must survive system reboot
182 |
183 | [Solution of Task11](#solution-of-task11)
184 |
185 | - ***Task 12 :***
186 | Create a playbook **/home/automation/plays/sysctl.yml** that runs on all inventory hosts and does the following:
187 | 1. If a server has more than 2048MB of RAM, then parameter vm.swappiness is set to 10.
188 | 2. If a server has less than 2048MB of RAM, then the following error message is displayed: Server memory less than 2048MB
189 |
190 | [Solution of Task12](#solution-of-task12)
191 |
192 |
193 | - ***Task 13 :***
194 | Create a playbook **/home/automation/plays/archive.yml** that runs on hosts in the database host group and does the following:
195 | 1. A file **/mnt/mysql_backups/database_list.txt** is created that contains the following line: dev,test,qa,prod.
196 | 2. A gzip archive of the file /mnt/mysql_backups/database_list.txt is created and stored in /mnt/mysql_backups/archive.gz
197 |
198 |
199 | [Solution of Task13](#solution-of-task13)
200 |
201 |
202 | - ***Task 14 :***
203 |
204 | Create a playbook **/home/automation/plays/packages.yml** that runs on all inventory hosts and does the following:
205 | 1. Installs tcpdump and mailx packages on hosts in the proxy host groups.
206 | 2. Installs lsof and mailx and packages on hosts in the database host groups.
207 |
208 | [Solution of Task14](#solution-of-task14)
209 |
210 | - ***Task 15 :***
211 | Create a playbook **/home/automation/plays/target.yml** that runs on hosts in the webserver host group and does the following:
212 | 1. Sets the default boot target to multi-user.
213 |
214 | [Solution of Task15](#solution-of-task15)
215 |
216 |
217 | - ***Task 16 :***
218 | Create a playbook **/home/automation/plays/server_list.yml** that does the following:
219 | 1. Playbook uses a Jinja2 template server_list.j2 to create a file /etc/server_list.txt on hosts in
220 | the database host group.
221 | 2. The file /etc/server_list.txt is owned by the automation user.
222 | 3. File permissions are set to 0600.
223 | 4. SELinux file label should be set to net_conf_t.
224 | 5. The content of the file is a list of FQDNs of all inventory hosts.
225 | After running the playbook, the content of the file /etc/server_list.txt should be the following:
226 | ansible2.hl.local
227 | ansible3.hl.local
228 | ansible4.hl.local
229 | ansible5.hl.local
230 | Note: if the FQDN of any inventory host changes, re-running the playbook should update the file
231 | with the new values.
232 |
233 | [Solution of Task16](#solution-of-task16)
234 |
235 |
236 | ### Solution of Task1
237 | ```yaml
238 | Ansible-installation :
239 | # yum list installed platform-python
240 | # yum install ansible
241 | # ansible --version
242 | 1- # useradd automation
243 | # echo "devops" | passwd --stdin automation
244 | 2- # su - automation
245 | # mkdir plays ; cd plays
246 | 3- # vim ansible.cfg
247 | ## Ansible.config file
248 | [defaults]
249 | role_path = ./roles
250 | inventory = ./inventory
251 | forks = 10
252 | remote_user = automation
253 | [privilege_escalation]
254 | become = False
255 |
256 | # vim inventory
257 | [proxy]
258 | ansible2.hl.local
259 | [webservers]
260 | ansible3.hl.local
261 | ansible4.hl.local
262 | [database]
263 | ansible5.hl.local
264 |
265 | # ansible all --list-hosts
266 | ```
267 | ### Solution of Task2
268 | ```bash
269 | # echo "automation ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/automation
270 | # ssh-keygen
271 | # vim adhoc.sh
272 | #!/bin/bash
273 | # you can specify the inventory file with -i option
274 | ansible all -m user -a "user='automation'\
275 | comment='User Create by Ansible'" -u root --ask-pass
276 |
277 | ansible all -m authorized_key -a "user=automation state=present \
278 | key={{ lookup('file', '/home/automation/.ssh/id_rsa.pub') }}" -u root --ask-pass
279 |
280 | ansible all -m copy -a "src='/etc/sudoers.d/automation' dest='/etc/sudoers.d/'" -u root --ask-pass
281 |
282 | # chmod 755 adhoc.sh
283 | # ./adhoc.sh
284 | ```
285 | ### Solution of Task3
286 |
287 | ```bash
288 | # mkdir group_vars ; cd group_vars
289 | # echo "message: Welcome to HAProxy server" >> proxy
290 | # echo "message: Welcome to Apache server" >> webserver
291 | # echo "message: Welcome to MySQLserver" >> database
292 |
293 | ```
294 | ```yaml
295 | ---
296 | - name: Customize the message of the day
297 | hosts: all
298 | tasks:
299 | - name: Create the message of the day according to the managed host
300 | copy:
301 | content: "{{ message }}"
302 | dest: /etc/motd
303 | owner: root
304 | group: root
305 | mode: '0644'
306 | ...
307 | ```
308 |
309 |
310 | ### Solution of Task4
311 | ```bash
312 | # vim defaults/main.yml
313 | # sshd config variables
314 | ssh_config:
315 | - start_line: "^banner"
316 | line: "banner /etc/motd"
317 | - start_line: "X11Forwarding"
318 | line: "X11Forwarding no"
319 | - start_line: "^#MaxAuthTries"
320 | line: "MaxAuthTries yes"
321 | ```
322 |
323 | ```yaml
324 | ---
325 | - name: Configure the sshd service
326 | hosts: all
327 | vars_files:
328 | - defaults/main.yml
329 | tasks:
330 | - name: Adding sshd config
331 | lineinfile:
332 | path: /etc/ssh/sshd_config
333 | regexp: "{{ item.start_line }}"
334 | line: "{{ item.line }}"
335 | loop: "{{ ssh_config }}"
336 | notify: restart sshd
337 | # don't forget to restart the service
338 | handler:
339 | - name: restart sshd
340 | service:
341 | name: sshd
342 | state: restarted
343 | ...
344 |
345 |
346 | # ansible all -m command -a 'grep "MaxAuthTries" /etc/ssh/sshd_config'
347 | ```
348 | ### Solution of Task5
349 | ```bash
350 | # ansible-vault create secret.yml
351 | New Vault password: devops
352 | Confirm New Vault password: devops
353 |
354 | ---
355 | user_password: devops
356 | database_password: devops
357 |
358 | using the decr with vault-file :
359 | # vim vault-key
360 | devops
361 | # chmod 400 vault-key
362 | # ansible-vault view secret.yml --vault-password-file vault-key
363 |
364 | ---
365 | user_password: devops
366 | database_password: devops
367 | ```
368 |
369 | ### Solution of Task6
370 | ```yaml
371 | ---
372 | - name: Create users
373 | hosts: all
374 | become: yes
375 | vars_files:
376 | - ./users_list.yml
377 | - ./secret.yml
378 | tasks:
379 | - name: Ensure group is exist
380 | group:
381 | name: wheel
382 | state: present
383 | - name: Create users that starts with 1 in their uid
384 | user:
385 | name: "{{ item.username }}"
386 | group: wheel
387 | password: "{{ user_password | password_hash('sha512') }}"
388 | shell: /bin/bash
389 | update_password: on_create
390 | with_items: "{{ users }}"
391 | when:
392 | - ansible_fqdn in groups['webservers']
393 | - "item.uid|string|first == '1'"
394 |
395 | - name: Create users that starts with 2 in their uid
396 | user:
397 | name: "{{ item.username }}"
398 | group: wheel
399 | password: "{{ user_password | password_hash('sha512') }}"
400 | shell: /bin/bash
401 | update_password: on_create
402 | with_items: "{{ users }}"
403 | when:
404 | - ansible_fqdn in groups['database']
405 | - "item.uid|string|first == '2'"
406 | ```
407 | ### Solution of Task7
408 | ```yaml
409 | ---
410 | - name: Scheduled tasks
411 | hosts: proxy
412 | become: yes
413 | tasks:
414 | - name: Ensure file exists
415 | file:
416 | path: /var/log/time.log
417 | state: touch
418 | mode: 0644
419 | - name: Create cronjob for root user
420 | cron:
421 | name: "check time"
422 | hour: "*/1"
423 | user: root
424 | job: "date >> /var/log/time.log"
425 | ```
426 | ### Solution of Task8
427 | ```yaml
428 | ---
429 | - name: Software repositories
430 | hosts: database
431 | become: yes
432 | tasks:
433 | - name: Create msyql repository
434 | yum_repository:
435 | name: mysql56-community
436 | description: "MySQL 5.6 YUM Repo"
437 | baseurl: "http://repo.mysql.com/yum/mysql-5.6-community/el/7/x86_64/"
438 | enabled: yes
439 | gpgcheck: yes
440 | gpgkey: "http://repo.mysql.com/RPM-GPG-KEY-mysql"
441 |
442 | # ansible database -m command -a 'cat /etc/yum.repos.d/MariaDB-10.5.repo' -b
443 | ```
444 | ### Solution of Task9
445 | ```yaml
446 | # cd roles
447 | # ansible-galaxy init sample-mysql
448 | # cd sample-mysql
449 | # vim vars/main.yml
450 |
451 | ---
452 | partitions:
453 | - number: 1
454 | start: 1MiB
455 | end: 800MiB
456 | device: /dev/sdb
457 |
458 | volume_groups:
459 | - name: vg_database
460 | device: /dev/sdb1
461 |
462 | logical_volumes:
463 | - name: lv_mysql
464 | size: 512MiB
465 | vgroup: vg_database
466 | mount_path: /mnt/mysql_backups
467 |
468 | mysql_service: mariadb
469 | mysql_packages:
470 | - mariadb
471 | - mariadb-server
472 | - python3-PyMySQL
473 | ...
474 |
475 |
476 | ```
477 |
478 | ```yaml
479 | # vim tasks/main.yml
480 | ---
481 | - name: Create a primary partition on /dev/sdb
482 | parted:
483 | device: "{{ item.device }}"
484 | number: "{{ item.number }}"
485 | part_start: "{{ item.start }}"
486 | part_end: "{{ item.end }}"
487 | part_type: primary
488 | state: present
489 | unit: MiB
490 | loop: "{{ partitions }}"
491 |
492 | - name: Ensure Volume group exist
493 | lvg:
494 | vg: "{{ item.name }}"
495 | pvs: "{{ item.device }}"
496 | loop: "{{ volume_groups }}"
497 |
498 | - name: Ensure Logical Volume exist
499 | lvol:
500 | lv: "{{ item.name }}"
501 | vg: "{{ item.vgroup }}"
502 | size: "{{ item.size }}"
503 | state: present
504 | loop: "{{ logical_volumes }}"
505 | when: item.name not in ansible_lvm["lvs"]
506 |
507 | - name: Create XFS filesystem
508 | filesystem:
509 | dev: "/dev/{{ item.vgroup }}/{{ item.name }}"
510 | type: xfs
511 | loop: "{{ logical_volumes }}"
512 |
513 | - name: Ensure Correct Capacity for {{ lv_name }}
514 | lvol:
515 | vg: "{{ item.vgroup }}"
516 | lv: "{{ item.name }}"
517 | size: "{{ item.size }}"
518 | resizefs: true
519 | force: yes
520 | loop: "{{ logical_volumes }}" ## remembre that the fs XFS does not support shrinking capacity
521 |
522 | - name: Ensure the FS is mounted
523 | mount:
524 | src: /dev/{{ item.vgroup }}/{{ item.name }}"
525 | path: "{{ item.mount_path }}"
526 | fstype: xfs
527 | state: mounted
528 | loop: "{{ logical_volumes }}"
529 |
530 | - name: Ensure mysql is installed
531 | yum:
532 | name: "{{ packages }}"
533 | state: present
534 |
535 | - name: Ensure MySQL is enabled and started
536 | service:
537 | name: "{{ mysql_service }}"
538 | state: started
539 | enabled: true
540 |
541 | - name: Enable MySQL in firewalld
542 | firewalld:
543 | service: "{{ mysql_service }}"
544 | state: enabled
545 | permanent: true
546 | immediate: true
547 |
548 | - name: Change MySQL root user password
549 | mysql_user:
550 | name: root
551 | password: "{{ database_password }}"
552 | state: present
553 |
554 | - name: Copy my.cnf.j2 to /etc/my.cnf
555 | template:
556 | src: my.cnf.j2
557 | dest: /etc/my.cnf
558 | notify: restart mysql
559 | ```
560 |
561 | ```yaml
562 | # vim handlers/main.yml
563 | ---
564 | - name: restart mysql
565 | service:
566 | name: "{{ mysql_srv }}"
567 | state: restarted
568 | ```
569 |
570 | ```yaml
571 | # vim templates/my.cfg.j2
572 | {{ ansible_managed }}
573 | [mysqld]
574 | bind_address = {{ ansible_facts['default_ipv4']['address'] }}
575 | skip_name_resolve
576 | datadir = /var/lib/mysql
577 | socket = /var/lib/mysql/mysql.sock
578 | symbolic-links = 0
579 | sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
580 | [mysqld_safe]
581 | log-error = /var/log/mysqld.log
582 | pid-file = /var/run/mysqld/mysqld.pid
583 | ```
584 |
585 | ```yaml
586 | # vim mysql.yml
587 | ---
588 | - name: Install mysql role
589 | hosts: databse
590 | vars_files:
591 | - secret.yml
592 | roles:
593 | sample-mysql
594 |
595 | ```
596 | ### Solution of Task10
597 | ```bash
598 | # ansible-galaxy install geerlingguy.haproxy -p roles/
599 | ```
600 | ```yml
601 | ---
602 | - name: Configure HAPROXY
603 | hosts: proxy
604 | become: yes
605 | roles:
606 | - geerlingguy.haproxy
607 | vars:
608 | haproxy_frontend_port: 80
609 | haproxy_frontend_mode: 'http'
610 | haproxy_backend_balance_method: 'roundrobin'
611 | haproxy_backend_servers:
612 | - name: app1
613 | address: 10.0.0.23 # The @ ip of the webservers
614 | - name: app2
615 | address: 10.0.0.25
616 | tasks:
617 | - name: Ensure firewalld and its dependencies are installed
618 | yum:
619 | name: firewalld
620 | state: latest
621 |
622 | - name: Ensure firewalld is running
623 | service:
624 | name: firewalld
625 | state: started
626 | enabled: yes
627 |
628 | - name: Ensure firewalld is allowing to the traffic
629 | firewalld:
630 | port: 80/tcp
631 | permanent: yes
632 | immediate: yes
633 | state: enabled
634 |
635 | # ansible proxy -m command -a 'systemctl is-enabled haproxy' -b
636 | # curl http://ansible2.hl.local/
637 | ```
638 | #### Solution of Task11
639 | > If you get stuck and forget the syntax, try this command :
640 |
641 | ```bash
642 | # find /usr/share/ -iname example-selinux*
643 | ```
644 | ```yml
645 | ---
646 | - name: Configure SELinux
647 | hosts: webservers
648 | become: true
649 | tasks:
650 | - name: Configure SELinux
651 | block:
652 | - include_role:
653 | name: rhel-system-roles.selinux
654 | rescue:
655 | # Fail if failed for a different reason than selinux_reboot_required.
656 | - name: handle errors
657 | fail:
658 | msg: "role failed"
659 | when: not selinux_reboot_required
660 | - name: restart managed host
661 | reboot:
662 | msg: "Ansible updates triggered"
663 | ignore_errors: true
664 |
665 | - name: wait for managed host to come back
666 | wait_for_connections:
667 | delay: 10
668 | timeout: 300
669 |
670 | - name: reapply the role
671 | include_role:
672 | name: rhel-system-roles.selinux
673 | ```
674 | ### Solution of Task12
675 | ```yaml
676 | ---
677 | - name: Set sysctl Parameters
678 | hosts: all
679 | become: true
680 | vars:
681 | min_ram_mb: 2048
682 | tasks:
683 |
684 | - name: Print error message
685 | debug:
686 | msg: "Server memory less than 2048MB"
687 | when: ansible_memtotal_mb < min_ram_mb
688 |
689 | - name: set vm.swappiness to 10
690 | sysctl:
691 | name: vm.swappiness
692 | value: '10'
693 | state: present
694 | when: ansible_memtotal_mb > min_ram_mb
695 | ```
696 | ### Solution of Task13
697 | ```yaml
698 | --
699 | - name: Use Archiving
700 | hosts: database
701 | become: yes
702 | tasks:
703 |
704 | - name: Create a directory if it does not exist
705 | file:
706 | path: /mnt/mysql_backups/
707 | state: directory
708 | mode: 0775
709 | owner: root
710 | group: root
711 |
712 | - name: Copy the content
713 | copy:
714 | content: "dev,test,qa,prod"
715 | dest: /mnt/mysql_backups/database_list.txt
716 |
717 | - name: Create archive
718 | archive:
719 | path: /mnt/mysql_backups/database_list.txt
720 | dest: /mnt/mysql_backups/archive.gz
721 | format: gz
722 | ```
723 | --### Solution of Task14
724 | ```yaml
725 | ---
726 | - name: Install packages
727 | hosts: all
728 | become: yes
729 | tasks:
730 |
731 | - name: Installs tcpdump and mailx packages on hosts in the proxy host groups
732 | yum:
733 | name:
734 | - tcpdump
735 | - mailx
736 | state: latest
737 | when: inventory_hostname in groups['proxy']
738 |
739 | - name: Installs lsof and mailx and packages on hosts in the database host groups
740 | yum:
741 | name:
742 | - lsof
743 | - mailx
744 | state: latest
745 | when: inventory_hostname in groups['database']
746 | ```
747 | ### Solution of Task15
748 | ```yaml
749 | ---
750 | - name: default boot target
751 | hosts: webservers
752 | become: yes
753 | tasks:
754 | - name: Set default boot target to multi-user
755 | file:
756 | src: /usr/lib/systemd/system/multi-user.target
757 | dest: /etc/systemd/system/default.target
758 | state: link
759 | ```
760 | ### Solution of Task16
761 | ```yaml
762 | # vim server_list.j2
763 | {% for host in groups['all'] %}
764 | {{ hostvars[host].inventory_hostname }}
765 | {% endfor %}
766 | ```
767 | ```yaml
768 | # vim server_list.yml
769 | ---
770 | - name: Create and Use Templates to Create Customised Configuration Files
771 | hosts: database
772 | become: yes
773 | tasks:
774 | - name: Create server list
775 | template:
776 | src: ./server_list.j2
777 | dest: /etc/server_list.txt
778 | owner: cloud_user
779 | mode: '0600'
780 | setype: net_conf_t
781 | ```
782 |
783 | #### RHCE8 Practice Exam 2
784 |
785 | - Will be updated soon
786 |
--------------------------------------------------------------------------------