Introduction

If no one has told you about this yet, then it is imperative for you to know that it is such a wonderful thing to be a Systems person in the current dispensation. The major reason for that is due to the number of tools in the form of technologies that have been developed and matured to help the operations team do their job augmented with a lot of fun and flexibility.

The hard days of manual administration is about to be laid to rest as a new breed of operations that leverages on automation takes the center stage. In order to show you the veracity of what is being applauded by this introductory portion of the guide, we are going to use Ansible to do some simple repetitive tasks such as creating new Linux users and copying files.

Example 1 – Install / Remove software packages on a remote system with Ansible

To install software packages on a remote system, use the package module which works for all systems supported by Ansible. This module actually calls the pertinent package modules for each system (apt, yum, etc). A specific module for OS like yum, apt can also be used.

--- 
- hosts: all 
  remote_user: tech
  become: true
  become_method: sudo
  tasks: 
    - name: Install Single Package using package module 
      package:
        name: vim
        state: present

    - name: Install Multiple packages using package module
      package:
        name: ['vim','wget','bash-completion','curl']
        state: present

    - name: Install package for Specific distro - apache on Debian or Ubuntu
      package:
        name: apache2
        state: present
      when: ansible_os_family == "Debian"

    - name: Install package for Specific distro - apache on CentOS / RHEL / Fedora
      package:
        name: httpd
        state: present
      when: ansible_os_family == "RedHat"

To remove a package, the state value should be set to absent.

Example 2 – Start / Stop Services on remote systems with Ansible

For service management, we’ll use the service module. We installed the Apache web server in Step 1, here we’ll start the service and set it to start at boot.

Since the service name is not the same for Debian and RedHat family, we have to Ansible condition.

--- 
- hosts: all 
  remote_user: tech
  become: true
  become_method: sudo
  tasks: 
    - name: Install Single Package using package module 
      package:
        name: vim
        state: present

    - name: Start apache service on Debian or Ubuntu
      service:
        name: apache2
        state: started
        enabled: yes
      when: ansible_os_family == "Debian"

    - name: Start apache service on CentOS / RHEL / Fedora
      service:
        name: httpd
        state: started
        enabled: yes
      when: ansible_os_family == "RedHat"

See all supported paramaters on Ansible service module documentation page.

Example 3 – Execute shell commands/script with Ansible

This example will demonstrate how to execute shell commands and shell script on the remote system.

--- 
- hosts: all 
  remote_user: tech
  become: true
  become_method: sudo
  tasks: 

    - name: Get Top 5 CPU consuming processes
      shell: ps aux | sort -nrk 3,3 | head -n 5
      register: top

    - name: Get Disk partitioning
      shell: df -hT
      register: df

    - debug: var=top.stdout_lines
    - debug: var=df.stdout_lines

You can also copy a local script to the server and execute it.

---
- name: Copy and execute a script.
  hosts: web-servers
  remote_user: user1
  become: yes
  become_method: sudo
  tasks:
     - name: Copy local script to remote systems
       copy:
         src: myscript.sh
         dest: /home/user1/myscript.sh
         mode: 0777

     - name: Execute a script on remote server
       command: sh /home/user1/myscript.sh

See my output below.

Example 4: Synchronize multiple directories from a remote Linux system to your local machine

For this to work, install rsync in your remote server since the Ansible module synchronize uses it. If you are keen, you will notice we are using “pull” mode of synchronize module to make this possible.

--- 
- hosts: portal 
  remote_user: tech
  become: true
  become_method: sudo
  tasks: 
    - name: Fetch Log Files from portal server and save them to local       
      synchronize:   
        src: "{{ item.source }}" 
        dest: "{{ item.dest }}" 
        mode: pull 
      with_items: 
        - { source: '/var/log/apps/Database/2019-08-07', dest: '/home/jtech/Documents/test3/Database' }
        - { source: '/var/log/apps/Exceptions/2019-08-07', dest: '/home/jtech/Documentss/test3/Exceptions' }
  • The hosts: portal is the remote server you expect to pull files from
  • source is the remote server’s directories you intend to pull and
  • dest is your local directories that will receive resources from the remote server.

Example 5: Adding users to a remote server using Ansible

The following is a yaml playbook that is going to add a user to many remote systems, add the user to respective sudoers file and copy the user’s public key to the remote servers. In the past, in case you wanted to add a new user to a couple of servers all of these would involve a lot of painful keyboard punching to get the work done. To use this playbook, we assume the following:

  • Ansible installed on the client machine
  • Another user (tech in this example) in the remote systems already exists with public keys from client machine copied to them and
  • Ansible is able to communicate with the remote servers effectively.

Open your /etc/ansible/hosts file and add the list of your remote servers at the end of the file. An example is shown below. If the ssh ports on the remote systems are not 22 by default, use a full colon and the ssh port number as shown as well.

Generate an encrypted user password:

$ mkpasswd --method=SHA-512 StrongUserPassword
$6$w4LFQ39hZz5$l9Uv3rMCJGqHuU1MbXFpJohY/zuDXNxQJhI3Y5wKvgxnaXnnQ/HnqHWhbgwr1w.7Xo.1yOAZ4AJuKAhUNvqhi.

$ mkpasswd --method=SHA-512
Password: 
$6$rz9Cx4SvxntT7pQp$VyWqxxkp4GNYml3t8Jlfo/DUXP4ELtfnLGq42GkhAIHq7VWuPRoFSl795rF1JOMycHmmYFTaYSRVO4/nZpWWm.

# With python passlib module
$ sudo pip install passlib
$ python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt('StrongUserPassword')"

The Playbook: users.yml

vim /etc/ansible/hosts

 [web-servers]
 192.168.10.20
 192.168.10.31:2023
 192.168.10.50

Create playbook.

---
- hosts: "web-servers"
  remote_user: tech
  become: true
  become_method: sudo
  vars:
    users:
    - "harry"
  tasks:
    - name: "Create user Harry in the remote web-servers"
      user:
        name: "{{ item }}"
        password: <encrypted-password>
        groups: "wheel"
        update_password: always
      register: user_created
      with_items: "{{ users }}"

    - name: "Add authorized keys"
      authorized_key:
      user: "{{ item }}"
        key: "{{ lookup('file', '/home/harry/.ssh/id_rsa.pub') }}"
        # key: "{{ lookup('file', 'files/'+ item + '.key.pub') }}"
      with_items: "{{ users }}"

    - name: Add user "harry" to sudo
      lineinfile:
        path: /etc/sudoers.d/harry
        line: 'harry ALL=(ALL) NOPASSWD: ALL'
        state: present
        mode: 0440
        create: yes
        validate: 'visudo -cf %s' 

    - name: Force user to change password
      shell: chage -d 0 {{ item }}
      when: user_created.changed 

Save this file in a directory of your choice and then run:

# ansible-playbook  users.yml -u tech -K

It will ask you for become password. Enter the password for the remote user in the system.

Example 6: Auto-create directories on your local machine and copy files in them from remote server.

Let’s say you often need to copy files from your remote server to your local machine and you are finally tired of copying them manually and now you would wish to use the efficiency of Ansible. The files in the remote server may be located in say:

/var/log/applications/web/20-08-08/, 
/var/log/applications/frontend/20-08-08/, 
/var/log/applications/backend/20-08-08/, 
/var/log/applications/frontend1/20-08-08/ and 
/var/log/applications/sockets/20-08-08/
/var/log/applications/others/20-08-08/

To copy the files in 20-08-08 sub-directories in the respective directories on your local machine neatly, you would need to create the respective directories to match what exists on your remote server. An example is creating files such as:

/home/tech/logs/web/20-08-08/, 
/home/tech/logs/frontend/20-08-08/, 
/home/tech/logs/backend/20-08-08/, 
/home/tech/logs/frontend1/20-08-08/ and 
/home/tech/logs/sockets/20-08-08/
/home/tech/logs/others/20-08-08/

Instead of manually creating those dierctories, Ansible can do it for you as described in this guide.

First, Ansible will auto-create the /home/tech/logs/ parent directory and then auto-create the various sub-directories (web,frontend,backend,frontend1,sockets) in it. Finally, the 20-08-08 sub-directories will be synchronized with your remote server’s sub-directories. You will find 20-08-08 directory and all of its files within it neatly copied on your local machine. Let us create the playbook to do this job.

Step One: Create a variables file in whatever directory and input all of your variables.

vim vars.yml
---
LOCAL_PROJECT_DIRECTORY:  "/home/tech/logs"
REMOTE_PROJECT_DIRECTORY: "/var/log/applications"

Step Two: Add your remote server to hosts file. This can be in your default file or on any host file you create.

vim /etc/ansible/hosts
#Add your host
[remoteserver]
192.168.20.23

Step Three: Create your playbook to copy the directories and files for you

vim playbook.yml

---
- hosts: 127.0.0.1    # Create directories and sub-directories in local machine in this play
  vars_files:
  ./variables1/vars.yaml
  tasks:
    - name: Auto-Create Local parent project directory {{ LOCAL_PROJECT_DIRECTORY }} and sub-directories
      file: path={{ LOCAL_PROJECT_DIRECTORY }}/{{ item }} state=directory
      with_items:
          - web
          - frontend
          - backend
          - Database
          - frontend1
          - sockets
          - others

- hosts: remoteserver      # Copy directories and files in local machine from remoteserver in this play
  vars_files:
  ./variables1/vars.yaml
  become: true
  
  tasks:
    - name: Fetch stuff from your remote server and save to locally autocreated directorie
      become: yes
      synchronize:   
        src: "{{ REMOTE_PROJECT_DIRECTORY }}/{{ item }}/20-08-08" 
        dest: "{{ LOCAL_PROJECT_DIRECTORY }}/{{ item }}/" 
        mode: pull 
      with_items: web
          - frontend
          - backend
          - Database
          - frontend1
          - sockets
          - others 

After you are done with that, it is time to run your playbook,

# ansible-playbook playbook.yaml -u tech -K

Input your sudo password on remote server and hit enter.

Example 7: Remove Old users in your system

---
- hosts: servers
  remote_user: tech
  become: true
  become_method: sudo
  vars:
    users:
    - "jack"
    - "tom"
    - "sharon"
    - "tech"
    - "pench"
  tasks:
    name: "Remove old users out of the system"
    user:
      name: "{{ item }}"
      state: "absent"
    with_items: "{{ users }}" 

Example 8: Checkout files from SVN server and copy them to a remote server

If you would wish to pull files from your subversion server and maybe copy them over to another location on a remote server with one Ansible command, then this guide shows how it can be done. Please follow through.

Step One: Create a variables file in whatever directory and input all of your variables.

$ vim vars.yml

---
LOCAL_PROJECT:  "/home/tech/svn"
REMOTE_PROJECT: "/var/log/applications"

Step Two: Add your remote server to hosts file. This can be in your default file or on any host file you create.

vim /etc/ansible/hosts

[remoteserver]
192.168.20.27

Step Three: Create a playbook to checkout files from subversion server to local machine and copy them to remote server automatically.

$ vim playbook.yml
---
- hosts: 127.0.0.1
  vars_files:
    - ./variables1/vars.yaml
  tasks:
   - name: Auto-Create Local project directory
     file: path={{ LOCAL_PROJECT }}/{{ item }} state=directory
     with_items:
         - App
   - name: Checkout subversion repository to the created directory/folder
     subversion:
       repo: https://path/to/your/subversion/
       username: user1
       password: strongpassword
       checkout: yes
       update: yes
       in_place: yes
       dest: "{{ LOCAL_PROJECT }}/{{ item }}"
     with_items:
         - App

- hosts: worker1
  vars_files:
    - ./variables1/vars.yaml
  tasks:
   - name: Auto-Create Remote project directory 
     become: yes 
     file: path={{ REMOTE_PROJECT }}/{{ item }} state=directory 
    with_items:
        - Application
   - name: Copy the checked-out files to remote server via Synchronize
     become: yes
     synchronize:
       src: "{{ LOCAL_PROJECT }}/{{ item.local }}/" 
       dest: "{{ REMOTE_PROJECT }}/{{ item.remote }}" 
     with_items:
         - { local: 'App', remote: 'Application' } 

Step Four: Since the playbook has sensitive data, that is, username and password, let us encrypt it with ansible-vault so that nobody can view your stuff.

Encrypt your playbook file as shown below. Enter a password and you will be good to go.

$ ansible-vault encrypt playbook.yml
New Vault password:
Confirm New Vault password:
Encryption successful

After that is complete, proceed to run your playbook with the options shown. It will prompt for sudo password for user1 and the ansible-vault password you have just entered above.

$ ansible-playbook playbook.yml --ask-vault-pass -u user1 -K
BECOME password:
Vault password:

PLAY [127.0.0.1] 
***********************************************************************
TASK [Gathering Facts] 
***********************************************************************
ok: [127.0.0.1]

Conclusion

Ansible can do much more complex things jus to ease your work as an Administrator. The guide was to simply show that it can handle even the simplest of tasks that can take up much of your time for no reason. Stay tuned for easier to follow guides.

Also read:

Best Books To learn Docker and Ansible Automation

How to use scp command to securely transfer files with examples

Top 10 Free Backup software for Linux

netstat vs ss usage guide on Linux

How to use rsync command on Linux/Unix with examples

How to Check TCP connections States in Linux with Netstat

How to extract .xz files on Linux – CenOS / Ubuntu / Debian

How To Customize Qcow2/Raw Linux OS disk image with virt-customize