├── 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 | ![image](image/redhat.png)
4 |   [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "MIT License") 5 |   [![Active](http://img.shields.io/badge/Status-Active-green.svg)](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 | --------------------------------------------------------------------------------