├── Adding-User.md ├── Docker-Module.md ├── Handlers.md ├── Host-Variables.md ├── Implement-First-Playbook.md ├── Important-Modules-Sample-Tasks.md ├── Install-Ansible-Basic-Commands.md ├── LICENSE ├── Managing-Files.md ├── Managing-Services.md ├── Multipass-SSH-Configuration.md ├── README.md ├── Refactoring-Playbook.md ├── Roles.md ├── Tags.md ├── Targeting-Specific-Node.md ├── Templates.md └── ansible_lab_files ├── ansible.cfg ├── docker_play.yml ├── files ├── default_site.html └── sudoer_newuser111 ├── inventory ├── roles ├── base │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── sshd_config_ubuntu.j2 ├── database_servers │ └── tasks │ │ └── main.yml └── web_servers │ ├── files │ └── default_site.html │ ├── handlers │ └── main.yml │ └── tasks │ └── main.yml ├── site.yml └── site_before_role.yml /Adding-User.md: -------------------------------------------------------------------------------- 1 | ## LAB: Adding User 2 | 3 | This scenario shows: 4 | - how to add user. 5 | 6 | ### Prerequisite 7 | 8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 10 | 11 | ### Steps 12 | 13 | - Update site.yml file, Add followings to add 'newuser111': 14 | 15 | ``` 16 | - name: create new user 17 | tags: always 18 | user: 19 | name: newuser111 20 | groups: root 21 | ``` 22 | 23 | - Updated site.yml 24 | 25 | ``` 26 | --- 27 | 28 | - hosts: all 29 | become: true 30 | pre_tasks: 31 | 32 | - name: install updates (CentOS) 33 | tags: always 34 | dnf: 35 | update_only: yes 36 | update_cache: yes 37 | when: ansible_distribution == "CentOS" 38 | 39 | - name: install updates (Ubuntu) 40 | tags: always 41 | apt: 42 | upgrade: dist 43 | update_cache: yes 44 | when: ansible_distribution == "Ubuntu" 45 | 46 | - name: create new user 47 | tags: always 48 | user: 49 | name: newuser111 50 | groups: root 51 | 52 | - hosts: web_servers 53 | become: true 54 | tasks: 55 | 56 | - name: install apache and php (CentOS) 57 | tags: centos,apache,httpd 58 | dnf: 59 | name: 60 | - httpd 61 | - php 62 | state: latest 63 | when: ansible_distribution == "CentOS" 64 | 65 | - name: install apache and php (Ubuntu) 66 | tags: ubuntu,apache,apache2 67 | apt: 68 | name: 69 | - apache2 70 | - libapache2-mod-php 71 | state: latest 72 | when: ansible_distribution == "Ubuntu" 73 | 74 | - name: start apache (Ubuntu) 75 | tags: ubuntu,apache,apache2 76 | service: 77 | name: apache2 78 | state: started 79 | enabled: yes 80 | when: ansible_distribution == "Ubuntu" 81 | 82 | - name: change email address for admin (Ubuntu) 83 | tags: ubuntu,apache,apache2 84 | lineinfile: 85 | path: /etc/apache2/sites-available/000-default.conf 86 | regexp: 'ServerAdmin webmaster@localhost' 87 | line: ' ServerAdmin somebody@somewhere.com' 88 | when: ansible_distribution == "Ubuntu" 89 | register: apache2_service 90 | 91 | - name: restart apache (Ubuntu) 92 | tags: ubuntu,apache,apache2 93 | service: 94 | name: apache2 95 | state: restarted 96 | when: apache2_service.changed 97 | 98 | - name: copy default (index) html file for site 99 | tags: apache,apache2,httpd 100 | copy: 101 | src: default_site.html 102 | dest: /var/www/html/index.html 103 | owner: root 104 | group: root 105 | mode: 0644 106 | 107 | - name: install unzip 108 | package: 109 | name: unzip 110 | 111 | - name: install terraform 112 | unarchive: 113 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 114 | dest: /usr/local/bin 115 | remote_src: yes 116 | owner: root 117 | group: root 118 | mode: 0755 119 | 120 | - hosts: database_servers 121 | become: true 122 | tasks: 123 | 124 | - name: install MariaDB (CentOS) 125 | tags: centos,db,mariadb 126 | dnf: 127 | name: mariadb 128 | state: latest 129 | when: ansible_distribution == "CentOS" 130 | 131 | - name: install MariaDB (Ubuntu) 132 | tags: ubuntu,db,mariadb-server 133 | apt: 134 | name: mariadb-server 135 | state: latest 136 | when: ansible_distribution == "Ubuntu" 137 | ``` 138 | 139 | - Run the playbook: 140 | 141 | ``` 142 | ansible-playbook --ask-become-pass site.yml 143 | ``` 144 | 145 |  146 | 147 | - Run on other nodes to check: 148 | 149 | ``` 150 | cat /etc/passwd 151 | ``` 152 | 153 |  154 | 155 | - Add SSH Key and sudoer file into 'site.yml': 156 | 157 | ``` 158 | - name: add ssh key for new user 159 | tags: always 160 | authorized_key: 161 | user: newuser111 162 | key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdEJ8xu1C0kJ4Y39x2bfptMQVdxnPDXrkjmDvB44oDV78yKWg/0B/kacMqiEaaiEyAedH> 163 | 164 | - name: add sudoers file for newuser111 165 | tags: always 166 | copy: 167 | src: sudoer_newuser111 168 | dest: /etc/sudoers.d/newuser111 169 | owner: root 170 | group: root 171 | mode: 0440 172 | ``` 173 | 174 | - Create sudoer_newuser111 file in files: 175 | 176 | ``` 177 | nano files/sudoer_newuser111 178 | # copy following into it 179 | newuser111 ALL=(ALL) NOPASSWD: ALL 180 | ``` 181 | 182 |  183 | 184 | ``` 185 | ansible-playbook --ask-become-pass site.yml 186 | ``` 187 | 188 |  189 | 190 | - We can see that newuser111 file is transferred to node1 191 | 192 | ``` 193 | sudo ls -l /etc/sudoers.d 194 | ``` 195 | 196 |  197 | 198 |  199 | 200 |  201 | 202 | 203 | - Update the 'ansible.cfg' file 204 | 205 | ``` 206 | [defaults] 207 | inventory = inventory 208 | # private_key_file = ~/.ssh/ansible 209 | remote_user = newuser111 210 | ``` 211 | - When we run ansible-playbook without become password (sudo), it works: 212 | 213 | ``` 214 | ansible-playbook site.yml 215 | ``` 216 | 217 |  218 | 219 | - Finally we created new user, added this user as sudoers and we can now use ansible-playbook without using become password 220 | -------------------------------------------------------------------------------- /Docker-Module.md: -------------------------------------------------------------------------------- 1 | ## LAB: Playing Docker Module 2 | 3 | This scenario shows: 4 | - how to install docker 5 | - how to pull and list docker images 6 | - how to run, stop, remove docker containers. 7 | 8 | ### Prerequisite 9 | 10 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 11 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 12 | 13 | ### Steps 14 | 15 | - Create docker_play.yml (nano docker_play.yml) 16 | - This file provides to install Docker, pull ubuntu image 17 | 18 | ``` 19 | --- 20 | - hosts: all 21 | become: true 22 | vars: 23 | container_count: 4 24 | default_container_name: docker 25 | default_container_image: ubuntu 26 | default_container_command: sleep 1d 27 | 28 | tasks: 29 | - name: Install aptitude 30 | tags: install 31 | apt: 32 | name: aptitude 33 | state: latest 34 | update_cache: true 35 | 36 | - name: Install required system packages 37 | tags: install 38 | apt: 39 | pkg: 40 | - apt-transport-https 41 | - ca-certificates 42 | - curl 43 | - software-properties-common 44 | - python3-pip 45 | - virtualenv 46 | - python3-setuptools 47 | state: latest 48 | update_cache: true 49 | 50 | - name: Add Docker GPG apt Key 51 | tags: install 52 | apt_key: 53 | url: https://download.docker.com/linux/ubuntu/gpg 54 | state: present 55 | 56 | - name: Add Docker Repository 57 | tags: install 58 | apt_repository: 59 | repo: deb https://download.docker.com/linux/ubuntu focal stable 60 | state: present 61 | 62 | - name: Update apt and install docker-ce 63 | tags: install 64 | apt: 65 | name: docker-ce 66 | state: latest 67 | update_cache: true 68 | 69 | - name: Install Docker Module for Python 70 | tags: install 71 | pip: 72 | name: docker 73 | 74 | - name: Pull default Docker image 75 | tags: pull 76 | docker_image: 77 | name: "{{ default_container_image }}" 78 | source: pull 79 | 80 | - name: Run default containers 81 | tags: run 82 | docker_container: 83 | name: "{{ default_container_name }}{{ item }}" 84 | image: "{{ default_container_image }}" 85 | command: "{{ default_container_command }}" 86 | state: present 87 | with_sequence: count={{ container_count }} 88 | 89 | - name: docker container ls -a 90 | tags: container_ls 91 | become: True 92 | shell: 93 | "docker container ls -a" 94 | register: container_info 95 | 96 | - name: docker container ls -a result 97 | tags: container_ls 98 | debug: 99 | msg: "{{container_info.stdout_lines}}" 100 | 101 | - name: docker images 102 | tags: image_ls 103 | become: True 104 | shell: 105 | "docker images" 106 | register: image_info 107 | 108 | - name: docker images result 109 | tags: image_ls 110 | debug: 111 | msg: "{{image_info.stdout_lines}}" 112 | 113 | - name: Stop containers 114 | tags: stop 115 | docker_container: 116 | name: "{{ default_container_name }}{{ item }}" 117 | state: stopped 118 | with_sequence: count={{ container_count }} 119 | 120 | - name: Remove containers 121 | tags: remove 122 | docker_container: 123 | name: "{{ default_container_name }}{{ item }}" 124 | state: absent 125 | with_sequence: count={{ container_count }} 126 | ``` 127 | 128 | - Run following command to run all, but we should use tags to run specific commands: 129 | 130 | ``` 131 | ansible-playbook docker_play.yml 132 | ``` 133 | 134 |  135 | 136 | 137 | ``` 138 | ssh 172.21.67.249 139 | sudo docker container ls -a 140 | ``` 141 | 142 |  143 | 144 | - To install docker on nodes: 145 | ``` 146 | ansible-playbook docker_play.yml --tags install 147 | ``` 148 | 149 | - To run (sudo docker container ls -a): 150 | ``` 151 | ansible-playbook docker_play.yml --tags container_ls 152 | ``` 153 | 154 |  155 | 156 | - To run (sudo docker images): 157 | ``` 158 | ansible-playbook docker_play.yml --tags image_ls 159 | ``` 160 | 161 |  162 | 163 | - To stop docker containers (in this case, containers are not up, their status is 'created'): 164 | 165 | ``` 166 | ansible-playbook docker_play.yml --tags stop 167 | ``` 168 | 169 | - To remove docker containers: 170 | 171 | ``` 172 | ansible-playbook docker_play.yml --tags remove 173 | ``` 174 | 175 |  176 | 177 | 178 | ### Sample Docker Tasks: 179 | 180 | - Sample Docker Tasks are taken from here: 181 | - https://docs.ansible.com/ansible/2.9/modules/docker_container_module.html#docker-container-module 182 | 183 | ``` 184 | - name: Create a data container 185 | docker_container: 186 | name: mydata 187 | image: busybox 188 | volumes: 189 | - /data 190 | 191 | - name: Re-create a redis container 192 | docker_container: 193 | name: myredis 194 | image: redis 195 | command: redis-server --appendonly yes 196 | state: present 197 | recreate: yes 198 | exposed_ports: 199 | - 6379 200 | volumes_from: 201 | - mydata 202 | 203 | - name: Restart a container 204 | docker_container: 205 | name: myapplication 206 | image: someuser/appimage 207 | state: started 208 | restart: yes 209 | links: 210 | - "myredis:aliasedredis" 211 | devices: 212 | - "/dev/sda:/dev/xvda:rwm" 213 | ports: 214 | - "8080:9000" 215 | - "127.0.0.1:8081:9001/udp" 216 | env: 217 | SECRET_KEY: "ssssh" 218 | # Values which might be parsed as numbers, booleans or other types by the YAML parser need to be quoted 219 | BOOLEAN_KEY: "yes" 220 | ``` 221 | 222 | ``` 223 | - name: Container present 224 | docker_container: 225 | name: mycontainer 226 | state: present 227 | image: ubuntu:14.04 228 | command: sleep infinity 229 | 230 | - name: Stop a container 231 | docker_container: 232 | name: mycontainer 233 | state: stopped 234 | 235 | - name: Start 4 load-balanced containers 236 | docker_container: 237 | name: "container{{ item }}" 238 | recreate: yes 239 | image: someuser/anotherappimage 240 | command: sleep 1d 241 | with_sequence: count=4 242 | 243 | - name: remove container 244 | docker_container: 245 | name: ohno 246 | state: absent 247 | ``` 248 | 249 | ``` 250 | - name: Syslogging output 251 | docker_container: 252 | name: myservice 253 | image: busybox 254 | log_driver: syslog 255 | log_options: 256 | syslog-address: tcp://my-syslog-server:514 257 | syslog-facility: daemon 258 | # NOTE: in Docker 1.13+ the "syslog-tag" option was renamed to "tag" for 259 | # older docker installs, use "syslog-tag" instead 260 | tag: myservice 261 | 262 | - name: Create db container and connect to network 263 | docker_container: 264 | name: db_test 265 | image: "postgres:latest" 266 | networks: 267 | - name: "{{ docker_network_name }}" 268 | 269 | - name: Start container, connect to network and link 270 | docker_container: 271 | name: sleeper 272 | image: ubuntu:14.04 273 | networks: 274 | - name: TestingNet 275 | ipv4_address: "172.1.1.100" 276 | aliases: 277 | - sleepyzz 278 | links: 279 | - db_test:db 280 | - name: TestingNet2 281 | ``` 282 | 283 | ``` 284 | - name: Start a container with a command 285 | docker_container: 286 | name: sleepy 287 | image: ubuntu:14.04 288 | command: ["sleep", "infinity"] 289 | 290 | - name: Add container to networks 291 | docker_container: 292 | name: sleepy 293 | networks: 294 | - name: TestingNet 295 | ipv4_address: 172.1.1.18 296 | links: 297 | - sleeper 298 | - name: TestingNet2 299 | ipv4_address: 172.1.10.20 300 | 301 | - name: Update network with aliases 302 | docker_container: 303 | name: sleepy 304 | networks: 305 | - name: TestingNet 306 | aliases: 307 | - sleepyz 308 | - zzzz 309 | ``` 310 | 311 | ``` 312 | - name: Remove container from one network 313 | docker_container: 314 | name: sleepy 315 | networks: 316 | - name: TestingNet2 317 | purge_networks: yes 318 | 319 | - name: Remove container from all networks 320 | docker_container: 321 | name: sleepy 322 | purge_networks: yes 323 | 324 | - name: Start a container and use an env file 325 | docker_container: 326 | name: agent 327 | image: jenkinsci/ssh-slave 328 | env_file: /var/tmp/jenkins/agent.env 329 | 330 | - name: Create a container with limited capabilities 331 | docker_container: 332 | name: sleepy 333 | image: ubuntu:16.04 334 | command: sleep infinity 335 | capabilities: 336 | - sys_time 337 | cap_drop: 338 | - all 339 | ``` 340 | 341 | ``` 342 | - name: Finer container restart/update control 343 | docker_container: 344 | name: test 345 | image: ubuntu:18.04 346 | env: 347 | arg1: "true" 348 | arg2: "whatever" 349 | volumes: 350 | - /tmp:/tmp 351 | comparisons: 352 | image: ignore # don't restart containers with older versions of the image 353 | env: strict # we want precisely this environment 354 | volumes: allow_more_present # if there are more volumes, that's ok, as long as `/tmp:/tmp` is there 355 | 356 | - name: Finer container restart/update control II 357 | docker_container: 358 | name: test 359 | image: ubuntu:18.04 360 | env: 361 | arg1: "true" 362 | arg2: "whatever" 363 | comparisons: 364 | '*': ignore # by default, ignore *all* options (including image) 365 | env: strict # except for environment variables; there, we want to be strict 366 | 367 | - name: Start container with healthstatus 368 | docker_container: 369 | name: nginx-proxy 370 | image: nginx:1.13 371 | state: started 372 | healthcheck: 373 | # Check if nginx server is healthy by curl'ing the server. 374 | # If this fails or timeouts, the healthcheck fails. 375 | test: ["CMD", "curl", "--fail", "http://nginx.host.com"] 376 | interval: 1m30s 377 | timeout: 10s 378 | retries: 3 379 | start_period: 30s 380 | 381 | - name: Remove healthcheck from container 382 | docker_container: 383 | name: nginx-proxy 384 | image: nginx:1.13 385 | state: started 386 | healthcheck: 387 | # The "NONE" check needs to be specified 388 | test: ["NONE"] 389 | ``` 390 | 391 | ``` 392 | - name: start container with block device read limit 393 | docker_container: 394 | name: test 395 | image: ubuntu:18.04 396 | state: started 397 | device_read_bps: 398 | # Limit read rate for /dev/sda to 20 mebibytes per second 399 | - path: /dev/sda 400 | rate: 20M 401 | device_read_iops: 402 | # Limit read rate for /dev/sdb to 300 IO per second 403 | - path: /dev/sdb 404 | rate: 300 405 | ``` 406 | 407 | ### All Docker Modules: 408 | 409 | - https://docs.ansible.com/ansible/2.9/modules/list_of_cloud_modules.html#docker 410 | 411 | ### Reference 412 | 413 | - https://www.digitalocean.com/community/tutorials/how-to-use-ansible-to-install-and-set-up-docker-on-ubuntu-20-04 414 | - https://docs.ansible.com/ansible/2.9/modules/docker_container_module.html#docker-container-module 415 | -------------------------------------------------------------------------------- /Handlers.md: -------------------------------------------------------------------------------- 1 | ## LAB: Handlers 2 | 3 | This scenario shows: 4 | - how to create handlers. 5 | 6 | ### Prerequisite 7 | 8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 10 | 11 | ### Steps 12 | 13 | - Open 'roles/web_servers/tasks/main.yml', update followings (add notify: restart_apache): 14 | - The variables defined near notify calls the task that is defined in 'handlers/main.yml' 15 | 16 | ``` 17 | - name: change email address for admin (Ubuntu) 18 | tags: ubuntu,apache,apache2 19 | lineinfile: 20 | path: /etc/apache2/sites-available/000-default.conf 21 | regexp: 'ServerAdmin webmaster@localhost' 22 | line: ' ServerAdmin somebody@somewhere.com' 23 | when: ansible_distribution == "Ubuntu" 24 | notify: restart_apache 25 | ``` 26 | 27 |  28 | 29 | 30 | - All 'roles/web_servers/tasks/main.yml': 31 | ``` 32 | - name: install apache and php 33 | tags: ubuntu,apache,apache2 34 | apt: 35 | name: 36 | - "{{ apache_package_name }}" 37 | - "{{ php_package_name }}" 38 | state: latest 39 | 40 | - name: start apache 41 | tags: ubuntu,apache,apache2 42 | service: 43 | name: "{{ apache_service }}" 44 | state: started 45 | enabled: yes 46 | 47 | - name: change email address for admin (Ubuntu) 48 | tags: ubuntu,apache,apache2 49 | lineinfile: 50 | path: /etc/apache2/sites-available/000-default.conf 51 | regexp: 'ServerAdmin webmaster@localhost' 52 | line: ' ServerAdmin somebody@somewhere.com' 53 | when: ansible_distribution == "Ubuntu" 54 | notify: restart_apache 55 | 56 | - name: copy default (index) html file for site 57 | tags: apache,apache2,httpd 58 | copy: 59 | src: default_site.html 60 | dest: /var/www/html/index.html 61 | owner: root 62 | group: root 63 | mode: 0644 64 | 65 | - name: install unzip 66 | package: 67 | name: unzip 68 | 69 | - name: install terraform 70 | unarchive: 71 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 72 | dest: /usr/local/bin 73 | remote_src: yes 74 | owner: root 75 | group: root 76 | mode: 0755 77 | ``` 78 | 79 | - Create 'handlers' directory under 'roles/web_servers' and create 'main.yml' 80 | 81 | ``` 82 | - name: restart_apache 83 | service: 84 | name: "{{ apache_service }}" 85 | state: restarted 86 | ``` 87 | 88 |  89 | 90 | - Run: 91 | 92 | ``` 93 | ansible-playbook site.yml 94 | ``` 95 | 96 | - Update the mail address to trigger the handler (restart_apache). Unless the task that has notify is changed, it cannot trigger handler task. 97 | 98 |  99 | 100 | - Handler is called. 101 | 102 |  103 | 104 | - File/Directory structure: 105 | 106 |  107 | 108 | 109 | -------------------------------------------------------------------------------- /Host-Variables.md: -------------------------------------------------------------------------------- 1 | ## LAB: Host Variables 2 | 3 | This scenario shows: 4 | - how to create host variables 5 | 6 | ### Prerequisite 7 | 8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 10 | 11 | ### Steps 12 | 13 | - Create 'host_vars' directory 14 | 15 | ``` 16 | mkdir host_vars 17 | ``` 18 | 19 |  20 | 21 | - If the nodes in the inventory are defined with IPs, create file with 'IP.yml' (if they are defined with domain name, files are 22 | 'domain_name.yml') 23 | 24 | - Add following variable into the file: 25 | 26 | ``` 27 | apache_package_name: apache2 28 | apache_service: apache2 29 | php_package_name: libapache2-mod-php 30 | ``` 31 | 32 |  33 | 34 | - We have host.yml files and host_vars in the yml file 35 | 36 |  37 | 38 | - Update 'roles/web_servers/tasks/main.yml' by adding variables (with quotation mark ") that are defined in files in host_vars directory. 39 | - For each node, defined host variables are used for variables. 40 | 41 | ``` 42 | - name: install apache and php 43 | tags: ubuntu,apache,apache2 44 | apt: 45 | name: 46 | - "{{ apache_package_name }}" 47 | - "{{ php_package_name }}" 48 | state: latest 49 | 50 | - name: start apache 51 | tags: ubuntu,apache,apache2 52 | service: 53 | name: "{{ apache_service }}" 54 | state: started 55 | enabled: yes 56 | 57 | - name: change email address for admin (Ubuntu) 58 | tags: ubuntu,apache,apache2 59 | lineinfile: 60 | path: /etc/apache2/sites-available/000-default.conf 61 | regexp: 'ServerAdmin webmaster@localhost' 62 | line: ' ServerAdmin somebody@somewhere.com' 63 | when: ansible_distribution == "Ubuntu" 64 | register: apache2_service 65 | 66 | - name: restart apache (Ubuntu) 67 | tags: ubuntu,apache,apache2 68 | service: 69 | name: "{{ apache_service }}" 70 | state: restarted 71 | when: apache2_service.changed 72 | 73 | - name: copy default (index) html file for site 74 | tags: apache,apache2,httpd 75 | copy: 76 | src: default_site.html 77 | dest: /var/www/html/index.html 78 | owner: root 79 | group: root 80 | mode: 0644 81 | 82 | - name: install unzip 83 | package: 84 | name: unzip 85 | 86 | - name: install terraform 87 | unarchive: 88 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 89 | dest: /usr/local/bin 90 | remote_src: yes 91 | owner: root 92 | group: root 93 | mode: 0755 94 | ``` 95 | 96 |  97 | 98 | Run: 99 | 100 | ``` 101 | ansible-playbook site.yml 102 | ``` 103 | 104 |  105 | 106 | -------------------------------------------------------------------------------- /Implement-First-Playbook.md: -------------------------------------------------------------------------------- 1 | ## LAB: Implement First Playbook 2 | 3 | This scenario shows: 4 | - how to create ansible playbooks 5 | - how to run "apt install" command in the playbook 6 | - how to run "update" command in the playbook 7 | - how to run "apt remove" command in the playbook 8 | - how to run command according to distribution (when) 9 | 10 | ### Prerequisite 11 | 12 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 13 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 14 | 15 | ### Steps 16 | 17 | - Create playbook to install apache2 app on nodes 18 | 19 | #### "Apt Install" command in the playbook 20 | 21 | ``` 22 | nano install_apache.yml 23 | # copy followings: 24 | --- 25 | 26 | - hosts: all 27 | become: true 28 | tasks: 29 | 30 | - name: install apache2 package 31 | apt: 32 | name: apache2 33 | ``` 34 | 35 |  36 | 37 |  38 | 39 | - Run playbook 40 | 41 | ``` 42 | ansible-playbook --ask-become-pass install_apache.yml 43 | ``` 44 | 45 | - Under Task "install apache2 package", status are changed, this means installing apache2 packet on the nodes successfully 46 | 47 |  48 | 49 | - If you run again that command, it is seen that "ok" under the Task "install apache2 package", it means that there is no change 50 | 51 |  52 | 53 | - When you enter the one of the nodes' IP on the browser, you can see that the apache2 server is installed on it 54 | 55 |  56 | 57 | - If you enter "never-existed-tect-package" as apt name, you can see that it cannot install on the nodes, because it does not exist. 58 | 59 |  60 | 61 |  62 | 63 | #### "Update" command in the playbook 64 | 65 | - Add "apt update" and install other packages 66 | 67 | ``` 68 | --- 69 | 70 | - hosts: all 71 | become: true 72 | tasks: 73 | 74 | - name: update repository index 75 | apt: 76 | update_cache: yes 77 | 78 | - name: install apache2 package 79 | apt: 80 | name: apache2 81 | 82 | - name: add php support for apache 83 | apt: 84 | name: libapache2-mod-php 85 | ``` 86 | 87 |  88 | 89 | ``` 90 | ansible-playbook --ask-become-pass install_apache.yml 91 | ``` 92 | 93 |  94 | 95 | - Add "state: latest" to install latest version of the app 96 | 97 | ``` 98 | --- 99 | 100 | - hosts: all 101 | become: true 102 | tasks: 103 | 104 | - name: update repository index 105 | apt: 106 | update_cache: yes 107 | 108 | - name: install apache2 package 109 | apt: 110 | name: apache2 111 | state: latest 112 | 113 | - name: add php support for apache 114 | apt: 115 | name: libapache2-mod-php 116 | state: latest 117 | ``` 118 | 119 |  120 | 121 | #### "Apt remove" command in the playbook 122 | 123 | - Create "remove_apache.yml" to uninstall apps. 124 | - Use "state:absent" to uninstall. 125 | 126 | ``` 127 | --- 128 | 129 | - hosts: all 130 | become: true 131 | tasks: 132 | 133 | - name: remove apache2 package 134 | apt: 135 | name: apache2 136 | state: absent 137 | 138 | - name: add php support for apache 139 | apt: 140 | name: libapache2-mod-php 141 | state: absent 142 | ``` 143 | 144 |  145 | 146 | ``` 147 | ansible-playbook --ask-become-pass remove_apache.yml 148 | ``` 149 | 150 |  151 | 152 | - When browsing IP to see whether apache2 works or not, it is seen that apache2 server was uninstalled. 153 | 154 |  155 | 156 | #### Command According to the Distribution ("when") 157 | 158 | - Add 'when: ansible-distribution == "Ubuntu"' into the install_apache.yaml file 159 | - With 'when', it is possible to install command on specific distro (e.g. Ubuntu, Centos) 160 | 161 | ``` 162 | --- 163 | 164 | - hosts: all 165 | become: true 166 | tasks: 167 | 168 | - name: update repository index 169 | apt: 170 | update_cache: yes 171 | when: ansible_distribution in ["Debian", "Ubuntu"] 172 | 173 | - name: install apache2 package 174 | apt: 175 | name: apache2 176 | state: latest 177 | when: ansible_distribution == "Ubuntu" 178 | 179 | - name: add php support for apache 180 | apt: 181 | name: libapache2-mod-php 182 | state: latest 183 | when: ansible_distribution == "Ubuntu" 184 | ``` 185 | - To get more information about the specific node. 186 | 187 | ``` 188 | ansible all -m gather_facts --limit 172.21.79.85 | grep ansible_distribution 189 | ``` 190 | 191 |  192 | 193 | - It is possible to use 'when' commands with other details (e.g. "ansible_distribution_version": "22.04") 194 | 195 | - Adding new tasks for 'CentOS' distribution 196 | 197 | ``` 198 | --- 199 | 200 | - hosts: all 201 | become: true 202 | tasks: 203 | 204 | - name: update repository index 205 | apt: 206 | update_cache: yes 207 | when: ansible_distribution in ["Debian", "Ubuntu"] 208 | 209 | - name: install apache2 package 210 | apt: 211 | name: apache2 212 | state: latest 213 | when: ansible_distribution == "Ubuntu" 214 | 215 | - name: add php support for apache 216 | apt: 217 | name: libapache2-mod-php 218 | state: latest 219 | when: ansible_distribution == "Ubuntu" 220 | 221 | - name: update repository index 222 | dnf: 223 | update_cache: yes 224 | when: ansible_distribution == "CentOS" 225 | 226 | - name: install apache2 package 227 | dnf: 228 | name: httpd 229 | state: latest 230 | when: ansible_distribution == "CentOS" 231 | 232 | - name: add php support for apache 233 | dnf: 234 | name: php 235 | state: latest 236 | when: ansible_distribution == "CentOS" 237 | ``` 238 | Run: 239 | ``` 240 | ansible-playbook --ask-become-pass install_apache.yml 241 | ``` 242 | - Tasks that are defined for 'CentOS' are skipped 243 | 244 |  245 | 246 | 247 | ### Reference 248 | 249 | - https://www.youtube.com/watch?v=VANub3AhZpI&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70&index=6 250 | -------------------------------------------------------------------------------- /Important-Modules-Sample-Tasks.md: -------------------------------------------------------------------------------- 1 | ## LAB: Important (Mostly Possible Used) Modules Sample Tasks 2 | 3 | This scenario shows the important (Mostly Possible Used) modules sample tasks: 4 | - [File Module](#file) 5 | - [Lineinfile Module](#lineinfile) 6 | - [Unarchive Module](#unarchive) 7 | - [Command Module](#command) 8 | - [Shell Module](#shell) 9 | - [Windows PsExec Module](#psexec) 10 | 11 | ### Prerequisite 12 | 13 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 14 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 15 | 16 | ### File Module 17 | 18 | Details: https://docs.ansible.com/ansible/2.9/modules/list_of_files_modules.html 19 | 20 | ``` 21 | - name: Change file ownership, group and permissions 22 | file: 23 | path: /etc/foo.conf 24 | owner: foo 25 | group: foo 26 | mode: '0644' 27 | 28 | - name: Give insecure permissions to an existing file 29 | file: 30 | path: /work 31 | owner: root 32 | group: root 33 | mode: '1777' 34 | 35 | - name: Create a symbolic link 36 | file: 37 | src: /file/to/link/to 38 | dest: /path/to/symlink 39 | owner: foo 40 | group: foo 41 | state: link 42 | 43 | - name: Create two hard links 44 | file: 45 | src: '/tmp/{{ item.src }}' 46 | dest: '{{ item.dest }}' 47 | state: hard 48 | loop: 49 | - { src: x, dest: y } 50 | - { src: z, dest: k } 51 | 52 | - name: Touch a file, using symbolic modes to set the permissions (equivalent to 0644) 53 | file: 54 | path: /etc/foo.conf 55 | state: touch 56 | mode: u=rw,g=r,o=r 57 | 58 | - name: Touch the same file, but add/remove some permissions 59 | file: 60 | path: /etc/foo.conf 61 | state: touch 62 | mode: u+rw,g-wx,o-rwx 63 | 64 | - name: Touch again the same file, but dont change times this makes the task idempotent 65 | file: 66 | path: /etc/foo.conf 67 | state: touch 68 | mode: u+rw,g-wx,o-rwx 69 | modification_time: preserve 70 | access_time: preserve 71 | 72 | - name: Create a directory if it does not exist 73 | file: 74 | path: /etc/some_directory 75 | state: directory 76 | mode: '0755' 77 | 78 | - name: Update modification and access time of given file 79 | file: 80 | path: /etc/some_file 81 | state: file 82 | modification_time: now 83 | access_time: now 84 | 85 | - name: Set access time based on seconds from epoch value 86 | file: 87 | path: /etc/another_file 88 | state: file 89 | access_time: '{{ "%Y%m%d%H%M.%S" | strftime(stat_var.stat.atime) }}' 90 | 91 | - name: Recursively change ownership of a directory 92 | file: 93 | path: /etc/foo 94 | state: directory 95 | recurse: yes 96 | owner: foo 97 | group: foo 98 | 99 | - name: Remove file (delete file) 100 | file: 101 | path: /etc/foo.txt 102 | state: absent 103 | 104 | - name: Recursively remove directory 105 | file: 106 | path: /etc/foo 107 | state: absent 108 | ``` 109 | 110 | ### LineInFile Module 111 | 112 | Details: https://docs.ansible.com/ansible/2.9/modules/lineinfile_module.html#lineinfile-module 113 | 114 | ``` 115 | # NOTE: Before 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path' 116 | - name: Ensure SELinux is set to enforcing mode 117 | lineinfile: 118 | path: /etc/selinux/config 119 | regexp: '^SELINUX=' 120 | line: SELINUX=enforcing 121 | 122 | - name: Make sure group wheel is not in the sudoers configuration 123 | lineinfile: 124 | path: /etc/sudoers 125 | state: absent 126 | regexp: '^%wheel' 127 | 128 | - name: Replace a localhost entry with our own 129 | lineinfile: 130 | path: /etc/hosts 131 | regexp: '^127\.0\.0\.1' 132 | line: 127.0.0.1 localhost 133 | owner: root 134 | group: root 135 | mode: '0644' 136 | 137 | - name: Ensure the default Apache port is 8080 138 | lineinfile: 139 | path: /etc/httpd/conf/httpd.conf 140 | regexp: '^Listen ' 141 | insertafter: '^#Listen ' 142 | line: Listen 8080 143 | 144 | - name: Ensure we have our own comment added to /etc/services 145 | lineinfile: 146 | path: /etc/services 147 | regexp: '^# port for http' 148 | insertbefore: '^www.*80/tcp' 149 | line: '# port for http by default' 150 | 151 | - name: Add a line to a file if the file does not exist, without passing regexp 152 | lineinfile: 153 | path: /tmp/testfile 154 | line: 192.168.1.99 foo.lab.net foo 155 | create: yes 156 | 157 | # NOTE: Yaml requires escaping backslashes in double quotes but not in single quotes 158 | - name: Ensure the JBoss memory settings are exactly as needed 159 | lineinfile: 160 | path: /opt/jboss-as/bin/standalone.conf 161 | regexp: '^(.*)Xms(\\d+)m(.*)$' 162 | line: '\1Xms${xms}m\3' 163 | backrefs: yes 164 | 165 | # NOTE: Fully quoted because of the ': ' on the line. See the Gotchas in the YAML docs. 166 | - name: Validate the sudoers file before saving 167 | lineinfile: 168 | path: /etc/sudoers 169 | state: present 170 | regexp: '^%ADMIN ALL=' 171 | line: '%ADMIN ALL=(ALL) NOPASSWD: ALL' 172 | validate: /usr/sbin/visudo -cf %s 173 | ``` 174 | 175 | ### Unarchive Module 176 | 177 | Details: https://docs.ansible.com/ansible/2.9/modules/unarchive_module.html#unarchive-module 178 | 179 | ``` 180 | - name: Extract foo.tgz into /var/lib/foo 181 | unarchive: 182 | src: foo.tgz 183 | dest: /var/lib/foo 184 | 185 | - name: Unarchive a file that is already on the remote machine 186 | unarchive: 187 | src: /tmp/foo.zip 188 | dest: /usr/local/bin 189 | remote_src: yes 190 | 191 | - name: Unarchive a file that needs to be downloaded (added in 2.0) 192 | unarchive: 193 | src: https://example.com/example.zip 194 | dest: /usr/local/bin 195 | remote_src: yes 196 | 197 | - name: Unarchive a file with extra options 198 | unarchive: 199 | src: /tmp/foo.zip 200 | dest: /usr/local/bin 201 | extra_opts: 202 | - --transform 203 | - s/^xxx/yyy/ 204 | ``` 205 | 206 | ### Command Module 207 | 208 | Details: https://docs.ansible.com/ansible/2.9/modules/command_module.html#command-module 209 | 210 | ``` 211 | - name: return motd to registered var 212 | command: cat /etc/motd 213 | register: mymotd 214 | 215 | - name: Run command if /path/to/database does not exist (without 'args' keyword). 216 | command: /usr/bin/make_database.sh db_user db_name creates=/path/to/database 217 | 218 | # 'args' is a task keyword, passed at the same level as the module 219 | - name: Run command if /path/to/database does not exist (with 'args' keyword). 220 | command: /usr/bin/make_database.sh db_user db_name 221 | args: 222 | creates: /path/to/database 223 | 224 | # 'cmd' is module parameter 225 | - name: Run command if /path/to/database does not exist (with 'cmd' parameter). 226 | command: 227 | cmd: /usr/bin/make_database.sh db_user db_name 228 | creates: /path/to/database 229 | 230 | - name: Change the working directory to somedir/ and run the command as db_owner if /path/to/database does not exist. 231 | command: /usr/bin/make_database.sh db_user db_name 232 | become: yes 233 | become_user: db_owner 234 | args: 235 | chdir: somedir/ 236 | creates: /path/to/database 237 | 238 | # 'argv' is a parameter, indented one level from the module 239 | - name: Use 'argv' to send a command as a list - leave 'command' empty 240 | command: 241 | argv: 242 | - /usr/bin/make_database.sh 243 | - Username with whitespace 244 | - dbname with whitespace 245 | 246 | - name: safely use templated variable to run command. Always use the quote filter to avoid injection issues. 247 | command: cat {{ myfile|quote }} 248 | register: myoutput 249 | ``` 250 | 251 | ### Shell Module 252 | 253 | Details: https://docs.ansible.com/ansible/2.9/modules/shell_module.html#shell-module 254 | 255 | ``` 256 | - name: Execute the command in remote shell; stdout goes to the specified file on the remote. 257 | shell: somescript.sh >> somelog.txt 258 | 259 | - name: Change the working directory to somedir/ before executing the command. 260 | shell: somescript.sh >> somelog.txt 261 | args: 262 | chdir: somedir/ 263 | 264 | # You can also use the 'args' form to provide the options. 265 | - name: This command will change the working directory to somedir/ and will only run when somedir/somelog.txt doesn't exist. 266 | shell: somescript.sh >> somelog.txt 267 | args: 268 | chdir: somedir/ 269 | creates: somelog.txt 270 | 271 | # You can also use the 'cmd' parameter instead of free form format. 272 | - name: This command will change the working directory to somedir/. 273 | shell: 274 | cmd: ls -l | grep log 275 | chdir: somedir/ 276 | 277 | - name: Run a command that uses non-posix shell-isms (in this example /bin/sh doesn't handle redirection and wildcards together but bash does) 278 | shell: cat < /tmp/*txt 279 | args: 280 | executable: /bin/bash 281 | 282 | - name: Run a command using a templated variable (always use quote filter to avoid injection) 283 | shell: cat {{ myfile|quote }} 284 | 285 | # You can use shell to run other executables to perform actions inline 286 | - name: Run expect to wait for a successful PXE boot via out-of-band CIMC 287 | shell: | 288 | set timeout 300 289 | spawn ssh admin@{{ cimc_host }} 290 | 291 | expect "password:" 292 | send "{{ cimc_password }}\n" 293 | 294 | expect "\n{{ cimc_name }}" 295 | send "connect host\n" 296 | 297 | expect "pxeboot.n12" 298 | send "\n" 299 | 300 | exit 0 301 | args: 302 | executable: /usr/bin/expect 303 | delegate_to: localhost 304 | 305 | # Disabling warnings 306 | - name: Using curl to connect to a host via SOCKS proxy (unsupported in uri). Ordinarily this would throw a warning. 307 | shell: curl --socks5 localhost:9000 http://www.ansible.com 308 | args: 309 | warn: no 310 | ``` 311 | 312 | ### Windows PsExec Module 313 | 314 | Details: https://docs.ansible.com/ansible/2.9/modules/psexec_module.html#psexec-module 315 | 316 | ``` 317 | - name: Run a cmd.exe command 318 | psexec: 319 | hostname: server 320 | connection_username: username 321 | connection_password: password 322 | executable: cmd.exe 323 | arguments: /c echo Hello World 324 | 325 | - name: Run a PowerShell command 326 | psexec: 327 | hostname: server.domain.local 328 | connection_username: username@DOMAIN.LOCAL 329 | connection_password: password 330 | executable: powershell.exe 331 | arguments: Write-Host Hello World 332 | 333 | - name: Send data through stdin 334 | psexec: 335 | hostname: 192.168.1.2 336 | connection_username: username 337 | connection_password: password 338 | executable: powershell.exe 339 | arguments: '-' 340 | stdin: | 341 | Write-Host Hello World 342 | Write-Error Error Message 343 | exit 0 344 | 345 | - name: Run the process as a different user 346 | psexec: 347 | hostname: server 348 | connection_user: username 349 | connection_password: password 350 | executable: whoami.exe 351 | arguments: /all 352 | process_username: anotheruser 353 | process_password: anotherpassword 354 | 355 | - name: Run the process asynchronously 356 | psexec: 357 | hostname: server 358 | connection_username: username 359 | connection_password: password 360 | executable: cmd.exe 361 | arguments: /c rmdir C:\temp 362 | asynchronous: yes 363 | 364 | - name: Use Kerberos authentication for the connection (requires smbprotocol[kerberos]) 365 | psexec: 366 | hostname: host.domain.local 367 | connection_username: user@DOMAIN.LOCAL 368 | executable: C:\some\path\to\executable.exe 369 | arguments: /s 370 | 371 | - name: Disable encryption to work with WIndows 7/Server 2008 (R2) 372 | psexec: 373 | hostanme: windows-pc 374 | connection_username: Administrator 375 | connection_password: Password01 376 | encrypt: no 377 | integrity_level: elevated 378 | process_username: Administrator 379 | process_password: Password01 380 | executable: powershell.exe 381 | arguments: (New-Object -ComObject Microsoft.Update.Session).CreateUpdateInstaller().IsBusy 382 | 383 | - name: Download and run ConfigureRemotingForAnsible.ps1 to setup WinRM 384 | psexec: 385 | hostname: '{{ hostvars[inventory_hostname]["ansible_host"] | default(inventory_hostname) }}' 386 | connection_username: '{{ ansible_user }}' 387 | connection_password: '{{ ansible_password }}' 388 | encrypt: yes 389 | executable: powershell.exe 390 | arguments: '-' 391 | stdin: | 392 | $ErrorActionPreference = "Stop" 393 | $sec_protocols = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::SystemDefault 394 | $sec_protocols = $sec_protocols -bor [Net.SecurityProtocolType]::Tls12 395 | [Net.ServicePointManager]::SecurityProtocol = $sec_protocols 396 | $url = "https://github.com/ansible/ansible/raw/devel/examples/scripts/ConfigureRemotingForAnsible.ps1" 397 | Invoke-Expression ((New-Object Net.WebClient).DownloadString($url)) 398 | exit 399 | delegate_to: localhost 400 | ``` 401 | -------------------------------------------------------------------------------- /Install-Ansible-Basic-Commands.md: -------------------------------------------------------------------------------- 1 | ## LAB: Install Ansible and Test Basic Ansible (Ad-Hoc) Commands 2 | 3 | This scenario shows: 4 | - how to install ansible 5 | - how to use basic commands 6 | 7 | ### Prerequisite 8 | 9 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 10 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 11 | 12 | ### Steps 13 | 14 | - Install Ansible on all nodes 15 | 16 | ``` 17 | sudo apt install ansible 18 | ``` 19 | 20 | - Create directory and inventory file to put managed nodes' IPs 21 | 22 |  23 | 24 | - Put the managed nodes' IPs into the inventory file 25 | 26 |  27 | 28 | - Ping all nodes with ansible 29 | 30 | ``` 31 | ansible all -i inventory -m ping 32 | ``` 33 | 34 |  35 | 36 | **NOTE:** If you use secure private SSH keys on each nodes (copied these keys on each nodes), it should be used "ansible all --key-file ~/.ssh -i inventory -m ping" 37 | 38 | - Create config file (ansible.cfg) 39 | 40 | ``` 41 | touch ansible.cfg 42 | # copy followings: 43 | [defaults] 44 | inventory = inventory 45 | # private_key_file = ~/.ssh/ansible 46 | ``` 47 | 48 |  49 | 50 |  51 | 52 | - Using config file (ansible.cfg), we can use short commands 53 | 54 |  55 | 56 | - List all hosts 57 | 58 | ``` 59 | ansible all --list-hosts 60 | ``` 61 |  62 | 63 | - Gather all nodes' information (all resources' information: cpu, ip, ssd, etc.) from all hosts 64 | 65 | ``` 66 | # -m parameter means ansible module 67 | ansible all -m gather_facts 68 | ``` 69 | 70 |  71 | 72 | - Gather information from specific node 73 | 74 | ``` 75 | ansible all -m gather_facts --limit 172.26.215.23 76 | ``` 77 | 78 | - Run "sudo apt update" for all nodes using ansible 79 | - As it is seen in the printscreen, it does not work. 80 | 81 | ``` 82 | ansible all -m apt -a update_cache=true 83 | ``` 84 | 85 |  86 | 87 | - The reason why "sudo apt update" does not work is to enter "sudo" password for all nodes. 88 | - For now, we are assigning same password for all nodes (node1, node2). Later, it will be shown for different passwords. 89 | 90 | ``` 91 | sudo passwd ubuntu 92 | ``` 93 | 94 |  95 |  96 |  97 | 98 | - Run "sudo apt update" for all nodes using "BECOME PASS", enter the common password when it asks 99 | 100 | ``` 101 | ansible all -m apt -a update_cache=true --become --ask-become-pass 102 | ``` 103 | 104 |  105 | 106 | - Install specific package "sudo apt get snapd" 107 | 108 | ``` 109 | ansible all -m apt -a name=snapd --become --ask-become-pass 110 | # latest version 111 | ansible all -m apt -a "name=snapd state=latest" --become --ask-become-pass 112 | ``` 113 | 114 |  115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Omer Berat Sezer 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 | -------------------------------------------------------------------------------- /Managing-Files.md: -------------------------------------------------------------------------------- 1 | ## LAB: Managing Files 2 | 3 | This scenario shows: 4 | - how to transfer file from control node to worker nodes. 5 | - how to download file from internet and unzip that file. 6 | 7 | ### Prerequisite 8 | 9 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 10 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 11 | 12 | ### Steps 13 | 14 | #### Transfer File from Control Node to Worker Nodes 15 | 16 | - Create html file in the control node. 17 | - Create directory and web page. 18 | 19 | ``` 20 | mkdir files 21 | nano files/default_site.html 22 | ``` 23 | 24 | ``` 25 | 26 |
Ansible Great!
30 | 31 | 32 | ``` 33 | 34 | - Update 'site.yml' file (implemented in [LAB: Adding Tags](https://github.com/omerbsezer/Fast-Ansible/blob/main/Tags.md)) 35 | 36 | ``` 37 | --- 38 | 39 | - hosts: all 40 | become: true 41 | pre_tasks: 42 | 43 | - name: install updates (CentOS) 44 | tags: always 45 | dnf: 46 | update_only: yes 47 | update_cache: yes 48 | when: ansible_distribution == "CentOS" 49 | 50 | - name: install updates (Ubuntu) 51 | tags: always 52 | apt: 53 | upgrade: dist 54 | update_cache: yes 55 | when: ansible_distribution == "Ubuntu" 56 | 57 | - hosts: web_servers 58 | become: true 59 | tasks: 60 | 61 | - name: install apache and php (CentOS) 62 | tags: centos,apache,httpd 63 | dnf: 64 | name: 65 | - httpd 66 | - php 67 | state: latest 68 | when: ansible_distribution == "CentOS" 69 | 70 | - name: install apache and php (Ubuntu) 71 | tags: ubuntu,apache,apache2 72 | apt: 73 | name: 74 | - apache2 75 | - libapache2-mod-php 76 | state: latest 77 | when: ansible_distribution == "Ubuntu" 78 | 79 | - name: copy default (index) html file for site 80 | tags: apache,apache2,httpd 81 | copy: 82 | src: default_site.html 83 | dest: /var/www/html/index.html 84 | owner: root 85 | group: root 86 | mode: 0644 87 | 88 | - hosts: database_servers 89 | become: true 90 | tasks: 91 | 92 | - name: install MariaDB (CentOS) 93 | tags: centos,db,mariadb 94 | dnf: 95 | name: mariadb 96 | state: latest 97 | when: ansible_distribution == "CentOS" 98 | 99 | - name: install MariaDB (Ubuntu) 100 | tags: ubuntu,db,mariadb-server 101 | apt: 102 | name: mariadb-server 103 | state: latest 104 | when: ansible_distribution == "Ubuntu" 105 | ``` 106 | 107 |  108 | 109 | - Run following: 110 | 111 | ``` 112 | ansible-playbook --ask-become-pass site.yml 113 | ``` 114 | 115 |  116 | 117 | - File is transferred to node1: 118 | 119 |  120 | 121 |  122 | 123 | #### Download File from Internet and Unzip the File 124 | 125 | - Update 'site.yml' file with adding unzip package (name: install unzip) and unarchive file (name: install terraform). 126 | 127 | ``` 128 | --- 129 | 130 | - hosts: all 131 | become: true 132 | pre_tasks: 133 | 134 | - name: install updates (CentOS) 135 | tags: always 136 | dnf: 137 | update_only: yes 138 | update_cache: yes 139 | when: ansible_distribution == "CentOS" 140 | 141 | - name: install updates (Ubuntu) 142 | tags: always 143 | apt: 144 | upgrade: dist 145 | update_cache: yes 146 | when: ansible_distribution == "Ubuntu" 147 | 148 | - hosts: web_servers 149 | become: true 150 | tasks: 151 | 152 | - name: install apache and php (CentOS) 153 | tags: centos,apache,httpd 154 | dnf: 155 | name: 156 | - httpd 157 | - php 158 | state: latest 159 | when: ansible_distribution == "CentOS" 160 | 161 | - name: install apache and php (Ubuntu) 162 | tags: ubuntu,apache,apache2 163 | apt: 164 | name: 165 | - apache2 166 | - libapache2-mod-php 167 | state: latest 168 | when: ansible_distribution == "Ubuntu" 169 | 170 | - name: copy default (index) html file for site 171 | tags: apache,apache2,httpd 172 | copy: 173 | src: default_site.html 174 | dest: /var/www/html/index.html 175 | owner: root 176 | group: root 177 | mode: 0644 178 | 179 | - name: install unzip 180 | package: 181 | name: unzip 182 | 183 | - name: install terraform 184 | unarchive: 185 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 186 | dest: /usr/local/bin 187 | remote_src: yes 188 | owner: root 189 | group: root 190 | mode: 0755 191 | 192 | - hosts: database_servers 193 | become: true 194 | tasks: 195 | 196 | - name: install MariaDB (CentOS) 197 | tags: centos,db,mariadb 198 | dnf: 199 | name: mariadb 200 | state: latest 201 | when: ansible_distribution == "CentOS" 202 | 203 | - name: install MariaDB (Ubuntu) 204 | tags: ubuntu,db,mariadb-server 205 | apt: 206 | name: mariadb-server 207 | state: latest 208 | when: ansible_distribution == "Ubuntu" 209 | ``` 210 | 211 |  212 | 213 | - It installs the zip file from remote and unzips this terraform application into '/usr/local/bin' 214 | 215 | ``` 216 | ansible-playbook --ask-become-pass site.yml 217 | ``` 218 | 219 |  220 | 221 | - Installed on node1 222 | 223 |  224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /Managing-Services.md: -------------------------------------------------------------------------------- 1 | ## LAB: Managing Services 2 | 3 | This scenario shows: 4 | - how to manage services 5 | 6 | ### Prerequisite 7 | 8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands 9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md) 10 | 11 | ### Steps 12 | 13 | #### Service Start 14 | 15 | - Update site.yml file, Add followings: 16 | ``` 17 | - name: start apache (Ubuntu) 18 | tags: ubuntu,apache,apache2 19 | service: 20 | name: apache2 21 | state: started 22 | enabled: yes 23 | when: ansible_distribution == "Ubuntu" 24 | ``` 25 | - Updated site.yml 26 | 27 | ``` 28 | --- 29 | 30 | - hosts: all 31 | become: true 32 | pre_tasks: 33 | 34 | - name: install updates (CentOS) 35 | tags: always 36 | dnf: 37 | update_only: yes 38 | update_cache: yes 39 | when: ansible_distribution == "CentOS" 40 | 41 | - name: install updates (Ubuntu) 42 | tags: always 43 | apt: 44 | upgrade: dist 45 | update_cache: yes 46 | when: ansible_distribution == "Ubuntu" 47 | 48 | - hosts: web_servers 49 | become: true 50 | tasks: 51 | 52 | - name: install apache and php (CentOS) 53 | tags: centos,apache,httpd 54 | dnf: 55 | name: 56 | - httpd 57 | - php 58 | state: latest 59 | when: ansible_distribution == "CentOS" 60 | 61 | - name: install apache and php (Ubuntu) 62 | tags: ubuntu,apache,apache2 63 | apt: 64 | name: 65 | - apache2 66 | - libapache2-mod-php 67 | state: latest 68 | when: ansible_distribution == "Ubuntu" 69 | 70 | - name: start apache (Ubuntu) 71 | tags: ubuntu,apache,apache2 72 | service: 73 | name: apache2 74 | state: started 75 | enabled: yes 76 | when: ansible_distribution == "Ubuntu" 77 | 78 | - name: copy default (index) html file for site 79 | tags: apache,apache2,httpd 80 | copy: 81 | src: default_site.html 82 | dest: /var/www/html/index.html 83 | owner: root 84 | group: root 85 | mode: 0644 86 | 87 | - name: install unzip 88 | package: 89 | name: unzip 90 | 91 | - name: install terraform 92 | unarchive: 93 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 94 | dest: /usr/local/bin 95 | remote_src: yes 96 | owner: root 97 | group: root 98 | mode: 0755 99 | 100 | - hosts: database_servers 101 | become: true 102 | tasks: 103 | 104 | - name: install MariaDB (CentOS) 105 | tags: centos,db,mariadb 106 | dnf: 107 | name: mariadb 108 | state: latest 109 | when: ansible_distribution == "CentOS" 110 | 111 | - name: install MariaDB (Ubuntu) 112 | tags: ubuntu,db,mariadb-server 113 | apt: 114 | name: mariadb-server 115 | state: latest 116 | when: ansible_distribution == "Ubuntu" 117 | ``` 118 | - Stop apache2 service and see the service is stopped. 119 | 120 | ``` 121 | systemctl stop apache2 122 | systemctl status apache2 123 | ``` 124 | 125 |  126 | 127 | - Run 128 | 129 | ``` 130 | ansible-playbook --ask-become-pass site.yml 131 | ``` 132 | 133 | - It is seen that apache2 service is started: 134 | 135 |  136 | 137 | #### Change Service Config File 138 | 139 | - Go to node1 and run: 140 | 141 | ``` 142 | sudo nano /etc/apache2/sites-available/000-default.conf 143 | ``` 144 | 145 |  146 | 147 | - Add following tasks into the webserver side of site.yml. 148 | 149 | ``` 150 | - name: change email address for admin (Ubuntu) 151 | tags: ubuntu,apache,apache2 152 | lineinfile: 153 | path: /etc/apache2/sites-available/000-default.conf 154 | regexp: '^ServerAdmin' 155 | line: ServerAdmin somebody@somewhere.com 156 | when: ansible_distribution == "Ubuntu" 157 | register: apache2_service 158 | 159 | - name: restart apache (Ubuntu) 160 | tags: ubuntu,apache,apache2 161 | service: 162 | name: apache2 163 | state: restarted 164 | when: apache2_service.changed 165 | ``` 166 | 167 | - As can seen printscreen, when the keyword is written in the register part (apache2_service), is changed, restart service is restarted. The task depends on the registered variable status. 168 | 169 |  170 | 171 | - **IMPORTANT:** If the register variable is defined consecutively, if second task does not run with same register variable (because first same task handled it), because second one does not change, so restart task does not run. 172 | 173 |  174 | 175 | - Updated site.yml: 176 | 177 | ``` 178 | --- 179 | 180 | - hosts: all 181 | become: true 182 | pre_tasks: 183 | 184 | - name: install updates (CentOS) 185 | tags: always 186 | dnf: 187 | update_only: yes 188 | update_cache: yes 189 | when: ansible_distribution == "CentOS" 190 | 191 | - name: install updates (Ubuntu) 192 | tags: always 193 | apt: 194 | upgrade: dist 195 | update_cache: yes 196 | when: ansible_distribution == "Ubuntu" 197 | 198 | - hosts: web_servers 199 | become: true 200 | tasks: 201 | 202 | - name: install apache and php (CentOS) 203 | tags: centos,apache,httpd 204 | dnf: 205 | name: 206 | - httpd 207 | - php 208 | state: latest 209 | when: ansible_distribution == "CentOS" 210 | 211 | - name: install apache and php (Ubuntu) 212 | tags: ubuntu,apache,apache2 213 | apt: 214 | name: 215 | - apache2 216 | - libapache2-mod-php 217 | state: latest 218 | when: ansible_distribution == "Ubuntu" 219 | 220 | - name: start apache (Ubuntu) 221 | tags: ubuntu,apache,apache2 222 | service: 223 | name: apache2 224 | state: started 225 | enabled: yes 226 | when: ansible_distribution == "Ubuntu" 227 | 228 | - name: change email address for admin (Ubuntu) 229 | tags: ubuntu,apache,apache2 230 | lineinfile: 231 | path: /etc/apache2/sites-available/000-default.conf 232 | regexp: 'ServerAdmin webmaster@localhost' 233 | line: ' ServerAdmin somebody@somewhere.com' 234 | when: ansible_distribution == "Ubuntu" 235 | register: apache2_service 236 | 237 | - name: restart apache (Ubuntu) 238 | tags: ubuntu,apache,apache2 239 | service: 240 | name: apache2 241 | state: restarted 242 | when: apache2_service.changed 243 | 244 | - name: copy default (index) html file for site 245 | tags: apache,apache2,httpd 246 | copy: 247 | src: default_site.html 248 | dest: /var/www/html/index.html 249 | owner: root 250 | group: root 251 | mode: 0644 252 | 253 | - name: install unzip 254 | package: 255 | name: unzip 256 | 257 | - name: install terraform 258 | unarchive: 259 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip 260 | dest: /usr/local/bin 261 | remote_src: yes 262 | owner: root 263 | group: root 264 | mode: 0755 265 | 266 | - hosts: database_servers 267 | become: true 268 | tasks: 269 | 270 | - name: install MariaDB (CentOS) 271 | tags: centos,db,mariadb 272 | dnf: 273 | name: mariadb 274 | state: latest 275 | when: ansible_distribution == "CentOS" 276 | 277 | - name: install MariaDB (Ubuntu) 278 | tags: ubuntu,db,mariadb-server 279 | apt: 280 | name: mariadb-server 281 | state: latest 282 | when: ansible_distribution == "Ubuntu" 283 | ``` 284 | 285 | - It can be seen that it is changed: 286 | 287 |  288 | 289 | ## Reference 290 | 291 | - https://www.youtube.com/watch?v=soeBHGAMkoQ&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70&index=12 292 | -------------------------------------------------------------------------------- /Multipass-SSH-Configuration.md: -------------------------------------------------------------------------------- 1 | ## LAB: Multipass-SSH-Configuration (Create Ansible Test Environment) 2 | 3 | This scenario shows: 4 | - how to install multipass 5 | - how to create control node, managed nodes 6 | - how to configure ssh between control node and managed nodes 7 | 8 | 9 | 10 | ### Steps 11 | 12 | - "Multipass is a mini-cloud on your workstation using native hypervisors of all the supported plaforms (Windows, macOS and Linux)" 13 | - Fast to install and to use. 14 | - **Link:** https://multipass.run/ 15 | - Install on Linux, Windows and MacOs: https://multipass.run/install 16 | - After installing, we can create VMs on our local machine. 17 | 18 | ``` 19 | # creating controlnode, managed nodes (node1, node2, etc.) 20 | # -c => cpu, -m => memory, -d => disk space 21 | multipass launch --name controlnode -c 2 -m 2G -d 10G 22 | multipass launch --name node1 -c 2 -m 2G -d 10G 23 | multipass launch --name node2 -c 2 -m 2G -d 10G 24 | multipass list 25 | ``` 26 | 27 |  28 | 29 | - Connect VMs by opening shells 30 | 31 | ``` 32 | # get shell on controlnode 33 | multipass shell controlnode 34 | # get shell on node1, on different terminal 35 | multipass shell node1 36 | # get shell on node2, on different terminal 37 | multipass shell node2 38 | ``` 39 | 40 |  41 | 42 | ``` 43 | sudo apt update 44 | sudo apt install net-tools 45 | # to see IPs 46 | ifconfig 47 | ``` 48 | 49 | - Create ssh public key on control plane 50 | - Copy the public key from control plane 51 | 52 | ``` 53 | > on controlnode 54 | ssh-keygen (no password, enter 3 times) 55 | cat ~/.ssh/id_rsa.pub (copy the value) 56 | ``` 57 | 58 |  59 | 60 | - Paste copied public key (control plane) into the authorized_keys in each managed nodes. 61 | 62 | ``` 63 | cd .ssh (on each workers) 64 | nano authorized_keys 65 | > Paste keys from controlnode (hence managed nodes know the controlnode IP and public key, controlnode can connect it) 66 | ``` 67 | 68 |  69 | 70 | - List all VMs to get IPs 71 | 72 | ``` 73 | multipass list 74 | ``` 75 | 76 |  77 | 78 | - SSH from controlplane to node1 79 | 80 | ``` 81 | ssh
200 |
201 | -name: Ensure the installed service is enabled and running
202 | service:
203 | name:
204 | ```
205 |
206 | - Playbooks include hostname, user information, and tasks (with modules):
207 |
208 | 
209 |
210 | - Go to LAB to learn how playbook is created:
211 | - [LAB: Implement First Playbook](https://github.com/omerbsezer/Fast-Ansible/blob/main/Implement-First-Playbook.md)
212 |
213 | - [LAB: Refactoring / Improving Playbook](https://github.com/omerbsezer/Fast-Ansible/blob/main/Refactoring-Playbook.md)
214 |
215 | ## Inventory File - Targeting Specific Nodes
216 |
217 | - For grouping the nodes (defining with names), we are using inventory file (nano inventory):
218 | ```
219 | [web_servers]
220 | 172.21.67.249
221 |
222 | [database_servers]
223 | 172.21.75.98
224 | ```
225 | - Go to LAB to create and use inventory file with playbook:
226 | - [LAB: Targeting Specific Nodes (Grouping)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Targeting-Specific-Node.md)
227 |
228 | ## Tags
229 | - With tags, some specific part of the code (playbook's play) could be run.
230 |
231 | ```
232 | ansible-playbook --tags ubuntu --ask-become-pass site.yml
233 | ```
234 |
235 | 
236 |
237 | - Go to LAB to learn how to use tags:
238 | - [LAB: Adding Tags](https://github.com/omerbsezer/Fast-Ansible/blob/main/Tags.md)
239 |
240 | ## Managing Files
241 | - It is possible to transfer file from control node to all workers nodes, to download zip file from internet and to unzip files with playbooks.
242 |
243 | 
244 |
245 | - Go to LAB to learn how:
246 | - [LAB: Managing Files](https://github.com/omerbsezer/Fast-Ansible/blob/main/Managing-Files.md)
247 |
248 | ## Managing Services
249 | - It is possible to manage services (create, start, stop, restart, configure service file)
250 |
251 | ```
252 | - name: start apache (Ubuntu)
253 | tags: ubuntu,apache,apache2
254 | service:
255 | name: apache2
256 | state: started
257 | enabled: yes
258 | when: ansible_distribution == "Ubuntu"
259 | ```
260 |
261 | - Go to LAB to learn how:
262 | - [LAB: Managing Services](https://github.com/omerbsezer/Fast-Ansible/blob/main/Managing-Services.md)
263 |
264 | ## Adding Users
265 | - It is possible to manage users (add users, create SSH keys for users, add user as sudoers)
266 |
267 | ```
268 | - name: create new user
269 | user:
270 | name: newuser111
271 | groups: root
272 | ```
273 |
274 | - Go to LAB to learn how:
275 | - [LAB: Adding Users](https://github.com/omerbsezer/Fast-Ansible/blob/main/Adding-User.md)
276 |
277 | ## Roles
278 | - Roles are defined to simplify, control your Ansible code like sofware code.
279 | - Roles are assigned to the group of nodes and roles help to define the task of these nodes.
280 |
281 | 
282 |
283 | - Go to LAB to learn how:
284 | - [LAB: Roles](https://github.com/omerbsezer/Fast-Ansible/blob/main/Roles.md)
285 |
286 | ## Host Variables
287 | - It helps to define variables which are dependent to the hosts.
288 |
289 | 
290 |
291 | 
292 |
293 | - Go to LAB to learn how:
294 | - [LAB: Host Variables](https://github.com/omerbsezer/Fast-Ansible/blob/main/Host-Variables.md)
295 |
296 | ## Handlers
297 | - To trigger/notify other Ansible code, handlers are used.
298 |
299 | 
300 |
301 | - Go to LAB to learn how:
302 | - [LAB: Handlers](https://github.com/omerbsezer/Fast-Ansible/blob/main/Handlers.md)
303 |
304 | ## Templates
305 | - Ansible template module does two things:
306 | - Replace the Jinja2 interpolation syntax variables present ({{ }}) in the template file with actual values.
307 | - Copy (scp) the file to the remote server.
308 |
309 | - Jinja2 interpolation syntax variables in the playbook (ref: middlewareinventory):
310 |
311 | 
312 |
313 | - In Ansible {{ }} is the interpolation syntax whereas in shell script it is ${ }
314 |
315 | - You can start your playbook like this with the variables at runtime.
316 |
317 | ```
318 | ansible-playbook findtest.yaml -e "DIR=/apps/Tomcat FILEEXT=*.log DAYSOLD=30"
319 | ```
320 |
321 | - Go to LAB to learn how:
322 | - [LAB: Templates](https://github.com/omerbsezer/Fast-Ansible/blob/main/Templates.md)
323 |
324 | ## Debugging
325 |
326 | - For verbosity, use -v, -vv (increase level), -vvv.
327 |
328 | ```
329 | ansible all -m shell -a uptime -v
330 | ansible all -m shell -a uptime -vv
331 | ansible all -m shell -a uptime -vvv
332 | ```
333 |
334 | ## Details
335 |
336 | ```
337 | ansible-playbook -f 10 # Run 10 hosts parallel, default f=5 hosts parallel
338 | ansible-playbook -C # Test run
339 | ansible-playbook -C -D # Dry run
340 | ansible-playbook --user # Log in as username (or -u )
341 | ansible-playbook --private-key # Log in using SSH key (usually in ~/.ssh) (or --key-file )
342 | ansible-playbook --ssh-extra-args # Pass extra command options to SSH
343 | ansible-playbook --vault-id # Use vault identity ID
344 | ansible-playbook --vault-password-file # Use vault password file key
345 | ansible-playbook --ask-vault-pass # Prompt for a vault password
346 | ansible-playbook --become # Escalate privileges
347 | ansible-playbook --ask-become-pass # Prompt for a password for become
348 | ansible-playbook -l # Run on single host
349 | ansible-playbook --list-hosts # Run Infos
350 | ansible-playbook --list-tasks # Run Infos
351 | ansible-playbook --syntax-check # Syntax Check
352 | ansible-playbook --check # Run the playbook but don’t make changes
353 | ansible-playbook --diff # Show diffs for what changes are made
354 |
355 | ```
356 |
357 | ### Capture Shell Output
358 | ```
359 | tasks:
360 | - name: some shell
361 | register: sh_out
362 | ignore_errors: yes
363 | become_user: root
364 | shell: |
365 | find /
366 |
367 | - name: "Print stdout"
368 | debug:
369 | msg: "{{ sh_out.stdout_lines }}"
370 | - name: "Print stderr"
371 | debug:
372 | msg: "{{ sh_out.stderr.split('\n') }}"
373 | ```
374 | - Debug output section in the playbook:
375 |
376 | 
377 |
378 | - Output:
379 |
380 | 
381 |
382 | ### Deleting files & directories
383 | ```
384 | tasks:
385 | - name: rm
386 | file:
387 | path:
388 | state: absent
389 | recurse: yes # optional
390 | ```
391 | ## Other Useful Resources Related Ansible
392 | - https://docs.ansible.com/ansible/2.9/
393 | - Video Tutorial: https://www.youtube.com/watch?v=3RiVKs8GHYQ&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70
394 | - https://www.tutorialspoint.com/ansible/
395 | - https://www.digitalocean.com/community/cheatsheets/how-to-use-ansible-cheat-sheet-guide
396 | - https://www.middlewareinventory.com/blog/category/ansible/
397 |
398 | ## References
399 | - OpenSource: https://opensource.com/resources/what-ansible
400 | - Video Tutorial: https://www.youtube.com/watch?v=3RiVKs8GHYQ&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70
401 | - https://www.kreyman.de/index.php/others/linux-kubernetes/213-ansible-verwendungsszenarien
402 | - https://ibm.github.io/cloud-enterprise-examples/iac-conf-mgmt/ansible/
403 | - Medium: https://medium.com/codex/automation-with-ansible-b39706ff777
404 | - RedHat Presentation: https://speakerdeck.com/chrisshort/using-ansible-for-devops?slide=27
405 | - https://www.middlewareinventory.com/blog/ansible-playbook-example/
406 | - https://www.digitalocean.com/community/cheatsheets/how-to-use-ansible-cheat-sheet-guide
407 | - https://www.middlewareinventory.com/blog/ansible-template-module-example/
408 |
--------------------------------------------------------------------------------
/Refactoring-Playbook.md:
--------------------------------------------------------------------------------
1 | ## LAB: Refactoring / Improving Playbook
2 |
3 | This scenario shows:
4 | - how to refactor / improve playbook
5 |
6 | ### Prerequisite
7 |
8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands
9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md)
10 |
11 | ### Steps
12 |
13 | - We have playbook that is created in this LAB: https://github.com/omerbsezer/Fast-Ansible/blob/main/Implement-First-Playbook.md
14 |
15 | ```
16 | ---
17 |
18 | - hosts: all
19 | become: true
20 | tasks:
21 |
22 | - name: update repository index
23 | apt:
24 | update_cache: yes
25 | when: ansible_distribution in ["Debian", "Ubuntu"]
26 |
27 | - name: install apache2 package
28 | apt:
29 | name: apache2
30 | state: latest
31 | when: ansible_distribution == "Ubuntu"
32 |
33 | - name: add php support for apache
34 | apt:
35 | name: libapache2-mod-php
36 | state: latest
37 | when: ansible_distribution == "Ubuntu"
38 |
39 | - name: update repository index
40 | dnf:
41 | update_cache: yes
42 | when: ansible_distribution == "CentOS"
43 |
44 | - name: install apache2 package
45 | dnf:
46 | name: httpd
47 | state: latest
48 | when: ansible_distribution == "CentOS"
49 |
50 | - name: add php support for apache
51 | dnf:
52 | name: php
53 | state: latest
54 | when: ansible_distribution == "CentOS"
55 | ```
56 |
57 | #### Consolidate same modules tasks into one task
58 |
59 | - Consolidate 'apt' and 'dnf' modules into one group both for Ubuntu and CentOS.
60 | - For both of them, they install two packages and update repository index.
61 | ```
62 | ---
63 |
64 | - hosts: all
65 | become: true
66 | tasks:
67 |
68 | - name: update repository index, install apache2 and php package for Ubuntu
69 | apt:
70 | name:
71 | - apache2
72 | - libapache2-mod-php
73 | state: latest
74 | update_cache: yes
75 | when: ansible_distribution == "Ubuntu"
76 |
77 | - name: update repository index, install apache2 and php package for CentOS
78 | dnf:
79 | name:
80 | - httpd
81 | - php
82 | state: latest
83 | update_cache: yes
84 | when: ansible_distribution == "CentOS"
85 | ```
86 |
87 | #### Consolidate into one task with Variables
88 |
89 | - Update install_apache.yml file and add variables: apache_package, php_package
90 | - Change 'apt' and 'dnf' to 'package'
91 |
92 | ```
93 | ---
94 |
95 | - hosts: all
96 | become: true
97 | tasks:
98 |
99 | - name: update repository index, install apache and php packages
100 | package:
101 | name:
102 | - "{{ apache_package }}"
103 | - "{{ php_package }}"
104 | state: latest
105 | update_cache: yes
106 | ```
107 |
108 | - Update inventory and add variables
109 |
110 | ```
111 | 172.21.79.85 apache_package=apache2 php_package=libapache2-mod-php
112 | 172.21.76.101 apache_package=apache2 php_package=libapache2-mod-php
113 | 172.21.76.102 apache_package=httpd php_package=php
114 | ```
115 |
116 | - Run:
117 |
118 | ```
119 | ansible-playbook --ask-become-pass install_apache.yml
120 | ```
121 |
122 | 
123 |
124 |
--------------------------------------------------------------------------------
/Roles.md:
--------------------------------------------------------------------------------
1 | ## LAB: Roles
2 |
3 | This scenario shows:
4 | - how to create roles
5 |
6 | ### Prerequisite
7 |
8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands
9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md)
10 |
11 | ### Steps
12 |
13 | - Update site.yml with 'roles'.
14 |
15 | ```
16 | ---
17 |
18 | - hosts: all
19 | become: true
20 | pre_tasks:
21 |
22 | - name: install updates (CentOS)
23 | tags: always
24 | dnf:
25 | update_only: yes
26 | update_cache: yes
27 | when: ansible_distribution == "CentOS"
28 |
29 | - name: install updates (Ubuntu)
30 | tags: always
31 | apt:
32 | upgrade: dist
33 | update_cache: yes
34 | when: ansible_distribution == "Ubuntu"
35 |
36 | - hosts: all
37 | become: true
38 | roles:
39 | - base
40 |
41 | - hosts: web_servers
42 | become: true
43 | roles:
44 | - web_servers
45 |
46 | - hosts: database_servers
47 | become: true
48 | roles:
49 | - database_servers
50 | ```
51 |
52 | 
53 |
54 | - Create directories.
55 |
56 | ```
57 | mkdir role
58 | cd role
59 | mkdir base
60 | mkdir web_servers
61 | mkdir database_servers
62 | ```
63 |
64 | 
65 |
66 | - Create subdirectories
67 |
68 | ```
69 | cd role
70 | mkdir base/tasks
71 | mkdir web_servers/tasks
72 | mkdir database_servers/tasks
73 | ```
74 |
75 | 
76 |
77 | - Create file 'main.yml' under 'role/base/tasks' with 'nano main.yml' and copy followings (taken from previous 'site.yml'):
78 |
79 | ```
80 | - name: add ssh key for new user
81 | authorized_key:
82 | user: newuser111
83 | key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdEJ8xu1C0kJ4Y39x2bfptMQVdxnPDXrkjmDvB44oDV78yKWg/0B/kacMqiEaaiEyAedHlk>
84 | ```
85 |
86 | - Create file 'main.yml' under 'role/database_servers/tasks' with 'nano main.yml' and copy followings (taken from previous 'site.yml'):
87 |
88 | ```
89 | - name: install MariaDB (CentOS)
90 | tags: centos,db,mariadb
91 | dnf:
92 | name: mariadb
93 | state: latest
94 | when: ansible_distribution == "CentOS"
95 |
96 | - name: install MariaDB (Ubuntu)
97 | tags: ubuntu,db,mariadb-server
98 | apt:
99 | name: mariadb-server
100 | state: latest
101 | when: ansible_distribution == "Ubuntu"
102 | ```
103 |
104 | - Create file 'main.yml' under 'role/web_servers/tasks' with 'nano main.yml' and copy followings (taken from previous 'site.yml'):
105 |
106 | ```
107 | - name: install apache and php (CentOS)
108 | tags: centos,apache,httpd
109 | dnf:
110 | name:
111 | - httpd
112 | - php
113 | state: latest
114 | when: ansible_distribution == "CentOS"
115 |
116 | - name: install apache and php (Ubuntu)
117 | tags: ubuntu,apache,apache2
118 | apt:
119 | name:
120 | - apache2
121 | - libapache2-mod-php
122 | state: latest
123 | when: ansible_distribution == "Ubuntu"
124 |
125 | - name: start apache (Ubuntu)
126 | tags: ubuntu,apache,apache2
127 | service:
128 | name: apache2
129 | state: started
130 | enabled: yes
131 | when: ansible_distribution == "Ubuntu"
132 |
133 | - name: change email address for admin (Ubuntu)
134 | tags: ubuntu,apache,apache2
135 | lineinfile:
136 | path: /etc/apache2/sites-available/000-default.conf
137 | regexp: 'ServerAdmin webmaster@localhost'
138 | line: ' ServerAdmin somebody@somewhere.com'
139 | when: ansible_distribution == "Ubuntu"
140 | register: apache2_service
141 |
142 | - name: restart apache (Ubuntu)
143 | tags: ubuntu,apache,apache2
144 | service:
145 | name: apache2
146 | state: restarted
147 | when: apache2_service.changed
148 |
149 | - name: copy default (index) html file for site
150 | tags: apache,apache2,httpd
151 | copy:
152 | src: default_site.html
153 | dest: /var/www/html/index.html
154 | owner: root
155 | group: root
156 | mode: 0644
157 |
158 | - name: install unzip
159 | package:
160 | name: unzip
161 |
162 | - name: install terraform
163 | unarchive:
164 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip
165 | dest: /usr/local/bin
166 | remote_src: yes
167 | owner: root
168 | group: root
169 | mode: 0755
170 | ```
171 |
172 | - Create directory 'roles/web_servers/files' and files in the 'files' directory
173 |
174 | ```
175 | mkdir files
176 | cp ../../files/default_site.html files/default_site.html
177 | ```
178 |
179 | 
180 |
181 | - Printscreen shows the structure of the directories. Structure should be like that, because Ansible finds the tasks with that way (e.g. roles/[nameofrole]/tasks/main.yml)
182 |
183 | 
184 |
185 | - Run ansible-playbook
186 |
187 | ```
188 | ansible-playbook site.yml
189 | ```
190 |
191 | 
192 |
193 |
--------------------------------------------------------------------------------
/Tags.md:
--------------------------------------------------------------------------------
1 | ## LAB: Adding Tags
2 |
3 | Tags are useful when we want to run specific part of the playbook. If we tagged with specific keywords, only tagged part would run.
4 |
5 | This scenario shows:
6 | - how to add tags and run according to specific tags
7 |
8 | ### Prerequisite
9 |
10 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands
11 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md)
12 |
13 | ### Steps
14 |
15 | - Tags are added with "tags" keyword. "tags: Always" run always, other tags could be custom defined (e.g. apache, mariadb, etc.)
16 |
17 | ```
18 | ---
19 |
20 | - hosts: all
21 | become: true
22 | pre_tasks:
23 |
24 | - name: install updates (CentOS)
25 | tags: always
26 | dnf:
27 | update_only: yes
28 | update_cache: yes
29 | when: ansible_distribution == "CentOS"
30 |
31 | - name: install updates (Ubuntu)
32 | tags: always
33 | apt:
34 | upgrade: dist
35 | update_cache: yes
36 | when: ansible_distribution == "Ubuntu"
37 |
38 | - hosts: web_servers
39 | become: true
40 | tasks:
41 |
42 | - name: install apache and php (CentOS)
43 | tags: centos,apache,httpd
44 | dnf:
45 | name:
46 | - httpd
47 | - php
48 | state: latest
49 | when: ansible_distribution == "CentOS"
50 |
51 | - name: install apache and php (Ubuntu)
52 | tags: ubuntu,apache,apache2
53 | apt:
54 | name:
55 | - apache2
56 | - libapache2-mod-php
57 | state: latest
58 | when: ansible_distribution == "Ubuntu"
59 |
60 | - hosts: database_servers
61 | become: true
62 | tasks:
63 |
64 | - name: install MariaDB (CentOS)
65 | tags: centos,db,mariadb
66 | dnf:
67 | name: mariadb
68 | state: latest
69 | when: ansible_distribution == "CentOS"
70 |
71 | - name: install MariaDB (Ubuntu)
72 | tags: ubuntu,db,mariadb-server
73 | apt:
74 | name: mariadb-server
75 | state: latest
76 | when: ansible_distribution == "Ubuntu"
77 | ```
78 |
79 | - To see the defined tags, run following:
80 |
81 | ```
82 | ansible-playbook --list-tags site.yml
83 | ```
84 |
85 | 
86 |
87 | - When we want to run only tasks which contains 'Ubuntu' tag, run following:
88 |
89 | ```
90 | ansible-playbook --tags ubuntu --ask-become-pass site.yml
91 | ```
92 |
93 | - It can be seen below, only 'ubuntu' tagged tasks and 'always' tagged tasks were run. "Gathering Facts" always run to collect server data.
94 |
95 | 
96 |
97 | - When we want to run only tasks which contains 'db' tag, run following:
98 |
99 | ```
100 | ansible-playbook --tags db --ask-become-pass site.yml
101 | ```
102 |
103 | - It can be seen below, only 'db' tagged tasks and 'always' tagged tasks were run.
104 |
105 | 
106 |
107 | - When we want to run only tasks which contains 'always' tag, run following:
108 |
109 | ```
110 | ansible-playbook --tags always --ask-become-pass site.yml
111 | ```
112 |
113 | 
114 |
--------------------------------------------------------------------------------
/Targeting-Specific-Node.md:
--------------------------------------------------------------------------------
1 | ## LAB: Targeting Specific Nodes
2 |
3 | This scenario shows:
4 | - how to target specific nodes
5 |
6 | ### Prerequisite
7 |
8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands
9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md)
10 |
11 | ### Steps
12 |
13 | - Update inventory file.
14 | - Make groups by giving names with '[]'.
15 |
16 | ```
17 | [web_servers]
18 | 172.21.79.85
19 |
20 | [database_servers]
21 | 172.21.76.101
22 | ```
23 |
24 | 
25 |
26 |
27 | - Create 'site.yml' file
28 | - To prioritize the tasks, for updating, 'pre_tasks' is used
29 | - For different hosts, 3 different host groups are created: all, web_servers and database_servers
30 | ```
31 | ---
32 |
33 | - hosts: all
34 | become: true
35 | pre_tasks:
36 |
37 | - name: install updates (CentOS)
38 | dnf:
39 | update_only: yes
40 | update_cache: yes
41 | when: ansible_distribution == "CentOS"
42 |
43 | - name: install updates (Ubuntu)
44 | apt:
45 | upgrade: dist
46 | update_cache: yes
47 | when: ansible_distribution == "Ubuntu"
48 |
49 | - hosts: web_servers
50 | become: true
51 | tasks:
52 |
53 | - name: install apache and php (CentOS)
54 | dnf:
55 | name:
56 | - httpd
57 | - php
58 | state: latest
59 | when: ansible_distribution == "CentOS"
60 |
61 | - name: install apache and php (Ubuntu)
62 | apt:
63 | name:
64 | - apache2
65 | - libapache2-mod-php
66 | state: latest
67 | when: ansible_distribution == "Ubuntu"
68 |
69 | - hosts: database_servers
70 | become: true
71 | tasks:
72 |
73 | - name: install MariaDB (CentOS)
74 | dnf:
75 | name: mariadb
76 | state: latest
77 | when: ansible_distribution == "CentOS"
78 |
79 | - name: install MariaDB (Ubuntu)
80 | apt:
81 | name: mariadb-server
82 | state: latest
83 | when: ansible_distribution == "Ubuntu"
84 | ```
85 |
86 | - Run
87 |
88 | ```
89 | ansible-playbook --ask-become-pass site.yml
90 | ```
91 |
92 | 
93 |
94 | - When we control whether mariadb is installed or not on database_servers (node2), it can be seen that it was installed on node2.
95 |
96 | ```
97 | multipass shell node2
98 | systemctl status mariadb
99 | ```
100 |
101 | 
102 |
103 |
--------------------------------------------------------------------------------
/Templates.md:
--------------------------------------------------------------------------------
1 | ## LAB: Templates
2 |
3 | This scenario shows:
4 | - how to create templates.
5 |
6 | ### Prerequisite
7 |
8 | - You should have a look following lab, nodes that are created in that LAB, are using in ansible commands
9 | - [LAB: Multipass-SSH Configuration (Create Ansible Test Environment)](https://github.com/omerbsezer/Fast-Ansible/blob/main/Multipass-SSH-Configuration.md)
10 |
11 | ### Steps
12 |
13 | - Create 'templates' directory under the '/roles/base/'
14 | - Copy 'sshd_config' file under 'templates' and create jinja2 file (.j2)
15 |
16 | ```
17 | mkdir templates
18 | cd templates
19 | cp /etc/ssh/sshd_config sshd_config_ubuntu.j2
20 | ```
21 |
22 | 
23 |
24 |
25 | - Open 'sshd_config_ubuntu.j2' file and add 'AllowUsers'.
26 |
27 | ```
28 | nano sshd_config_ubuntu.j2
29 | # add following
30 | AllowUsers {{ ssh_users }}
31 | ```
32 |
33 | 
34 |
35 | - Go to 'host_vars' directory,
36 | - Change the content of this host_vars files
37 |
38 | ```
39 | nano 172.21.69.156.yml
40 | # add following
41 | ssh_users: "newuser2022"
42 | ssh_template_file: sshd_config_ubuntu.j2
43 | ```
44 |
45 | 
46 |
47 | - File contents:
48 |
49 | ```
50 | apache_package_name: apache2
51 | apache_service: apache2
52 | php_package_name: libapache2-mod-php
53 | ssh_users: "newuser2022"
54 | ssh_template_file: sshd_config_ubuntu.j2
55 | ```
56 |
57 | 
58 |
59 | - Add another task to use templates
60 |
61 | 
62 |
63 | - Open and add ('nano main.yml')
64 | - After generating sshh_config file, it triggers handler (restart_ssh)
65 |
66 | ```
67 | - name: generate sshd_config file using templates
68 | tags: ssh
69 | template:
70 | src: "{{ ssh_template_file }}"
71 | dest: /etc/ssh/sshd_config
72 | owner: root
73 | group: root
74 | mode: 0644
75 | notify: restart_sshd
76 | ```
77 |
78 | 
79 |
80 | - Create handlers and create 'main.yml' file
81 |
82 | ```
83 | - name: restart_sshd
84 | service:
85 | name: sshd
86 | state: restarted
87 | ```
88 |
89 | 
90 |
91 | - Run:
92 |
93 | ```
94 | ansible-playbook site.yml
95 | ```
96 | 
97 |
98 | - After running playbook, when we go to the 'node1' to see the content of sshd_config ('nano /etc/ssh/sshd_config').
99 | - 'AllowUsers newuser2022' is added.
100 |
101 | 
102 |
103 | ## Reference
104 |
105 | - https://www.youtube.com/watch?v=s8F_YWGHeDM&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70&index=17
106 |
107 |
--------------------------------------------------------------------------------
/ansible_lab_files/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | inventory = inventory
3 | # private_key_file = ~/.ssh/ansible
4 | #remote_user = newuser111
--------------------------------------------------------------------------------
/ansible_lab_files/docker_play.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: all
3 | become: true
4 | vars:
5 | container_count: 4
6 | default_container_name: docker
7 | default_container_image: ubuntu
8 | default_container_command: sleep 1d
9 |
10 | tasks:
11 | - name: Install aptitude
12 | tags: install
13 | apt:
14 | name: aptitude
15 | state: latest
16 | update_cache: true
17 |
18 | - name: Install required system packages
19 | tags: install
20 | apt:
21 | pkg:
22 | - apt-transport-https
23 | - ca-certificates
24 | - curl
25 | - software-properties-common
26 | - python3-pip
27 | - virtualenv
28 | - python3-setuptools
29 | state: latest
30 | update_cache: true
31 |
32 | - name: Add Docker GPG apt Key
33 | tags: install
34 | apt_key:
35 | url: https://download.docker.com/linux/ubuntu/gpg
36 | state: present
37 |
38 | - name: Add Docker Repository
39 | tags: install
40 | apt_repository:
41 | repo: deb https://download.docker.com/linux/ubuntu focal stable
42 | state: present
43 |
44 | - name: Update apt and install docker-ce
45 | tags: install
46 | apt:
47 | name: docker-ce
48 | state: latest
49 | update_cache: true
50 |
51 | - name: Install Docker Module for Python
52 | tags: install
53 | pip:
54 | name: docker
55 |
56 | - name: Pull default Docker image
57 | tags: pull
58 | docker_image:
59 | name: "{{ default_container_image }}"
60 | source: pull
61 |
62 | - name: Run default containers
63 | tags: run
64 | docker_container:
65 | name: "{{ default_container_name }}{{ item }}"
66 | image: "{{ default_container_image }}"
67 | command: "{{ default_container_command }}"
68 | state: present
69 | with_sequence: count={{ container_count }}
70 |
71 | - name: docker container ls -a
72 | tags: container_ls
73 | become: True
74 | shell:
75 | "docker container ls -a"
76 | register: container_info
77 |
78 | - name: docker container ls -a result
79 | tags: container_ls
80 | debug:
81 | msg: "{{container_info.stdout_lines}}"
82 |
83 | - name: docker images
84 | tags: image_ls
85 | become: True
86 | shell:
87 | "docker images"
88 | register: image_info
89 |
90 | - name: docker images result
91 | tags: image_ls
92 | debug:
93 | msg: "{{image_info.stdout_lines}}"
94 |
95 | - name: Stop containers
96 | tags: stop
97 | docker_container:
98 | name: "{{ default_container_name }}{{ item }}"
99 | state: stopped
100 | with_sequence: count={{ container_count }}
101 |
102 | - name: Remove containers
103 | tags: remove
104 | docker_container:
105 | name: "{{ default_container_name }}{{ item }}"
106 | state: absent
107 | with_sequence: count={{ container_count }}
--------------------------------------------------------------------------------
/ansible_lab_files/files/default_site.html:
--------------------------------------------------------------------------------
1 |
2 | Ansible File Transfer Test
3 |
4 |
5 | Ansible Great!
6 |
7 |
--------------------------------------------------------------------------------
/ansible_lab_files/files/sudoer_newuser111:
--------------------------------------------------------------------------------
1 | newuser111 ALL=(ALL) NOPASSWD: ALL
--------------------------------------------------------------------------------
/ansible_lab_files/inventory:
--------------------------------------------------------------------------------
1 | [web_servers]
2 | 172.21.67.249
3 |
4 | [database_servers]
5 | 172.21.75.98
--------------------------------------------------------------------------------
/ansible_lab_files/roles/base/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: restart_sshd
2 | service:
3 | name: sshd
4 | state: restarted
--------------------------------------------------------------------------------
/ansible_lab_files/roles/base/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: add ssh key for new user
2 | authorized_key:
3 | user: newuser111
4 | key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdEJ8xu1C0kJ4Y39x2bfptMQVdxnPDXrkjmDvB44oDV78yKWg/0B/kacMqiEaaiEyAedHlk/FlKai9q82Lm5+0XD/WgXKlPUpyDJcUr8PmVEtBZwXwePXxiDTSy3/pUqrlrxtwbwlPDOeD6gpTbJLYetO6Beb7LmhcpV2RF6Gjvi3tB2NdND6O+umQJu1OD0sNIvfa34zft2Ov/17CC1mOHi3N4aisEfBSMT6yjtffLL9chyO5jwaX8RKNp80yqy4zp6sjfb4BuUZVaX1aTGWZjU7dFf34wz20rbak2ddXrtpt740gGWa8+ie/WBXiwzzxFatD7P2TSnY54jKaO1YPtYhYQ5SzlzNl0gEV3p9cLzbABnrVMDlRkZQ/pa75uyERAvxYYyAiJxlDibEMcDbUj1al+uzMwz7d+ISpsXc4LZmEzDZuDZm5ZLKFFiqxPWPEujDmAWNxXpw040vCmhhL3/BDkW1BkcTR16q2dqFuDxyqJJHLGNwj0g837iTGYzE= ubuntu@controlnode"
5 |
6 | - name: generate sshd_config file using templates
7 | tags: ssh
8 | template:
9 | src: "{{ ssh_template_file }}"
10 | dest: /etc/ssh/sshd_config
11 | owner: root
12 | group: root
13 | mode: 0644
14 | notify: restart_sshd
--------------------------------------------------------------------------------
/ansible_lab_files/roles/base/templates/sshd_config_ubuntu.j2:
--------------------------------------------------------------------------------
1 |
2 | # This is the sshd server system-wide configuration file. See
3 | # sshd_config(5) for more information.
4 |
5 | # This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
6 |
7 | # The strategy used for options in the default sshd_config shipped with
8 | # OpenSSH is to specify options with their default value where
9 | # possible, but leave them commented. Uncommented options override the
10 | # default value.
11 |
12 | Include /etc/ssh/sshd_config.d/*.conf
13 |
14 | #Port 22
15 | #AddressFamily any
16 | #ListenAddress 0.0.0.0
17 | #ListenAddress ::
18 |
19 | AllowUsers {{ ssh_users }}
20 |
21 | #HostKey /etc/ssh/ssh_host_rsa_key
22 | #HostKey /etc/ssh/ssh_host_ecdsa_key
23 | #HostKey /etc/ssh/ssh_host_ed25519_key
24 |
25 | # Ciphers and keying
26 | #RekeyLimit default none
27 |
28 | # Logging
29 | #SyslogFacility AUTH
30 | #LogLevel INFO
31 |
32 | # Authentication:
33 |
34 | #LoginGraceTime 2m
35 | #PermitRootLogin prohibit-password
36 | #StrictModes yes
37 | #MaxAuthTries 6
38 | #MaxSessions 10
39 |
40 | #PubkeyAuthentication yes
41 |
42 | # Expect .ssh/authorized_keys2 to be disregarded by default in future.
43 | #AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
44 |
45 | #AuthorizedPrincipalsFile none
46 |
47 | #AuthorizedKeysCommand none
48 | #AuthorizedKeysCommandUser nobody
49 |
50 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
51 | #HostbasedAuthentication no
52 | # Change to yes if you don't trust ~/.ssh/known_hosts for
53 | # HostbasedAuthentication
54 | #IgnoreUserKnownHosts no
55 | # Don't read the user's ~/.rhosts and ~/.shosts files
56 | #IgnoreRhosts yes
57 |
58 | # To disable tunneled clear text passwords, change to no here!
59 | PasswordAuthentication no
60 | #PermitEmptyPasswords no
61 |
62 | # Change to yes to enable challenge-response passwords (beware issues with
63 | # some PAM modules and threads)
64 | KbdInteractiveAuthentication no
65 |
66 | # Kerberos options
67 | #KerberosAuthentication no
68 | #KerberosOrLocalPasswd yes
69 | #KerberosTicketCleanup yes
70 | #KerberosGetAFSToken no
71 |
72 | # GSSAPI options
73 | #GSSAPIAuthentication no
74 | #GSSAPICleanupCredentials yes
75 | #GSSAPIStrictAcceptorCheck yes
76 | #GSSAPIKeyExchange no
77 |
78 | # Set this to 'yes' to enable PAM authentication, account processing,
79 | # and session processing. If this is enabled, PAM authentication will
80 | # be allowed through the KbdInteractiveAuthentication and
81 | # PasswordAuthentication. Depending on your PAM configuration,
82 | # PAM authentication via KbdInteractiveAuthentication may bypass
83 | # the setting of "PermitRootLogin without-password".
84 | # If you just want the PAM account and session checks to run without
85 | # PAM authentication, then enable this but set PasswordAuthentication
86 | # and KbdInteractiveAuthentication to 'no'.
87 | UsePAM yes
88 |
89 | #AllowAgentForwarding yes
90 | #AllowTcpForwarding yes
91 | #GatewayPorts no
92 | X11Forwarding yes
93 | #X11DisplayOffset 10
94 | #X11UseLocalhost yes
95 | #PermitTTY yes
96 | PrintMotd no
97 | #PrintLastLog yes
98 | #TCPKeepAlive yes
99 | #PermitUserEnvironment no
100 | #Compression delayed
101 | #ClientAliveInterval 0
102 | #ClientAliveCountMax 3
103 | #UseDNS no
104 | #PidFile /run/sshd.pid
105 | #MaxStartups 10:30:100
106 | #PermitTunnel no
107 | #ChrootDirectory none
108 | #VersionAddendum none
109 |
110 | # no default banner path
111 | #Banner none
112 |
113 | # Allow client to pass locale environment variables
114 | AcceptEnv LANG LC_*
115 |
116 | # override default of no subsystems
117 | Subsystem sftp /usr/lib/openssh/sftp-server
118 |
119 | # Example of overriding settings on a per-user basis
120 | #Match User anoncvs
121 | # X11Forwarding no
122 | # AllowTcpForwarding no
123 | # PermitTTY no
124 | # ForceCommand cvs server
--------------------------------------------------------------------------------
/ansible_lab_files/roles/database_servers/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: install MariaDB (CentOS)
2 | tags: centos,db,mariadb
3 | dnf:
4 | name: mariadb
5 | state: latest
6 | when: ansible_distribution == "CentOS"
7 |
8 | - name: install MariaDB (Ubuntu)
9 | tags: ubuntu,db,mariadb-server
10 | apt:
11 | name: mariadb-server
12 | state: latest
13 | when: ansible_distribution == "Ubuntu"
--------------------------------------------------------------------------------
/ansible_lab_files/roles/web_servers/files/default_site.html:
--------------------------------------------------------------------------------
1 |
2 | Ansible File Transfer Test
3 |
4 |
5 | Ansible Great!
6 |
7 |
--------------------------------------------------------------------------------
/ansible_lab_files/roles/web_servers/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: restart_apache
2 | service:
3 | name: "{{ apache_service }}"
4 | state: restarted
--------------------------------------------------------------------------------
/ansible_lab_files/roles/web_servers/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: install apache and php
2 | tags: ubuntu,apache,apache2
3 | apt:
4 | name:
5 | - "{{ apache_package_name }}"
6 | - "{{ php_package_name }}"
7 | state: latest
8 |
9 | - name: start apache
10 | tags: ubuntu,apache,apache2
11 | service:
12 | name: "{{ apache_service }}"
13 | state: started
14 | enabled: yes
15 |
16 | - name: change email address for admin (Ubuntu)
17 | tags: ubuntu,apache,apache2
18 | lineinfile:
19 | path: /etc/apache2/sites-available/000-default.conf
20 | regexp: 'ServerAdmin webmaster@localhost'
21 | line: ' ServerAdmin somebody@somewhere2.com'
22 | when: ansible_distribution == "Ubuntu"
23 | notify: restart_apache
24 |
25 | - name: copy default (index) html file for site
26 | tags: apache,apache2,httpd
27 | copy:
28 | src: default_site.html
29 | dest: /var/www/html/index.html
30 | owner: root
31 | group: root
32 | mode: 0644
33 |
34 | - name: install unzip
35 | package:
36 | name: unzip
37 |
38 | - name: install terraform
39 | unarchive:
40 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip
41 | dest: /usr/local/bin
42 | remote_src: yes
43 | owner: root
44 | group: root
45 | mode: 0755
--------------------------------------------------------------------------------
/ansible_lab_files/site.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - hosts: all
4 | become: true
5 | pre_tasks:
6 |
7 | - name: install updates (CentOS)
8 | tags: always
9 | dnf:
10 | update_only: yes
11 | update_cache: yes
12 | when: ansible_distribution == "CentOS"
13 |
14 | - name: install updates (Ubuntu)
15 | tags: always
16 | apt:
17 | upgrade: dist
18 | update_cache: yes
19 | when: ansible_distribution == "Ubuntu"
20 |
21 | - hosts: all
22 | become: true
23 | roles:
24 | - base
25 |
26 | - hosts: web_servers
27 | become: true
28 | roles:
29 | - web_servers
30 |
31 | - hosts: database_servers
32 | become: true
33 | roles:
34 | - database_servers
--------------------------------------------------------------------------------
/ansible_lab_files/site_before_role.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - hosts: all
4 | become: true
5 | pre_tasks:
6 |
7 | - name: install updates (CentOS)
8 | tags: always
9 | dnf:
10 | update_only: yes
11 | update_cache: yes
12 | when: ansible_distribution == "CentOS"
13 |
14 | - name: install updates (Ubuntu)
15 | tags: always
16 | apt:
17 | upgrade: dist
18 | update_cache: yes
19 | when: ansible_distribution == "Ubuntu"
20 |
21 | - name: create new user
22 | tags: always
23 | user:
24 | name: newuser111
25 | groups: root
26 |
27 | - name: add ssh key for new user
28 | tags: always
29 | authorized_key:
30 | user: newuser111
31 | key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdEJ8xu1C0kJ4Y39x2bfptMQVdxnPDXrkjmDvB44oDV78yKWg/0B/kacMqiEaaiEyAedHlk/FlKai9q82Lm5+0XD/WgXKlPUpyDJcUr8PmVEtBZwXwePXxiDTSy3/pUqrlrxtwbwlPDOeD6gpTbJLYetO6Beb7LmhcpV2RF6Gjvi3tB2NdND6O+umQJu1OD0sNIvfa34zft2Ov/17CC1mOHi3N4aisEfBSMT6yjtffLL9chyO5jwaX8RKNp80yqy4zp6sjfb4BuUZVaX1aTGWZjU7dFf34wz20rbak2ddXrtpt740gGWa8+ie/WBXiwzzxFatD7P2TSnY54jKaO1YPtYhYQ5SzlzNl0gEV3p9cLzbABnrVMDlRkZQ/pa75uyERAvxYYyAiJxlDibEMcDbUj1al+uzMwz7d+ISpsXc4LZmEzDZuDZm5ZLKFFiqxPWPEujDmAWNxXpw040vCmhhL3/BDkW1BkcTR16q2dqFuDxyqJJHLGNwj0g837iTGYzE= ubuntu@controlnode"
32 |
33 | - name: add sudoers file for newuser111
34 | tags: always
35 | copy:
36 | src: sudoer_newuser111
37 | dest: /etc/sudoers.d/newuser111
38 | owner: root
39 | group: root
40 | mode: 0440
41 |
42 | - hosts: web_servers
43 | become: true
44 | tasks:
45 |
46 | - name: install apache and php (CentOS)
47 | tags: centos,apache,httpd
48 | dnf:
49 | name:
50 | - httpd
51 | - php
52 | state: latest
53 | when: ansible_distribution == "CentOS"
54 |
55 | - name: install apache and php (Ubuntu)
56 | tags: ubuntu,apache,apache2
57 | apt:
58 | name:
59 | - apache2
60 | - libapache2-mod-php
61 | state: latest
62 | when: ansible_distribution == "Ubuntu"
63 |
64 | - name: start apache (Ubuntu)
65 | tags: ubuntu,apache,apache2
66 | service:
67 | name: apache2
68 | state: started
69 | enabled: yes
70 | when: ansible_distribution == "Ubuntu"
71 |
72 | - name: change email address for admin (Ubuntu)
73 | tags: ubuntu,apache,apache2
74 | lineinfile:
75 | path: /etc/apache2/sites-available/000-default.conf
76 | regexp: 'ServerAdmin webmaster@localhost'
77 | line: ' ServerAdmin somebody@somewhere.com'
78 | when: ansible_distribution == "Ubuntu"
79 | register: apache2_service
80 |
81 | - name: restart apache (Ubuntu)
82 | tags: ubuntu,apache,apache2
83 | service:
84 | name: apache2
85 | state: restarted
86 | when: apache2_service.changed
87 |
88 | - name: copy default (index) html file for site
89 | tags: apache,apache2,httpd
90 | copy:
91 | src: default_site.html
92 | dest: /var/www/html/index.html
93 | owner: root
94 | group: root
95 | mode: 0644
96 |
97 | - name: install unzip
98 | package:
99 | name: unzip
100 |
101 | - name: install terraform
102 | unarchive:
103 | src: https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_amd64.zip
104 | dest: /usr/local/bin
105 | remote_src: yes
106 | owner: root
107 | group: root
108 | mode: 0755
109 |
110 | - hosts: database_servers
111 | become: true
112 | tasks:
113 |
114 | - name: install MariaDB (CentOS)
115 | tags: centos,db,mariadb
116 | dnf:
117 | name: mariadb
118 | state: latest
119 | when: ansible_distribution == "CentOS"
120 |
121 | - name: install MariaDB (Ubuntu)
122 | tags: ubuntu,db,mariadb-server
123 | apt:
124 | name: mariadb-server
125 | state: latest
126 | when: ansible_distribution == "Ubuntu"
--------------------------------------------------------------------------------