Setting Ansible for My Home Lab

Since the weather was so nice I figured it would be a great idea to take the day off and work on my home lab. To start off I know that I am pretty comfortable with Ansible so I’d like to use that to build it all out. One thing that always bugged me was the directory structure. The first time I invested a lot into Ansible I went with the Alternative Directory Layout and it made things harder to leverage something across my environment. Since then I’d like to think that I have matured and learned from my mistakes. I have also begun to understand the value and importance of a monorepo so I am going to go with the standard Directory Layout:

production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1                 # here we assign variables to particular groups
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here
   hostname2              # ""

library/                  # if any custom modules, put them here (optional)
module_utils/             # if any custom module_utils to support modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

Adding a User

First off I created a new role for the purose of adding a user. I added my user, added a public key, and granted sudo privilege.

- name: Make sure my users is on the host
  become: yes
  user:
    name: ramon
    comment: "Ramon Gonzalez"

- name: Make sure to add my public key for ssh-key auth
  become: yes
  authorized_key:
    user: ramon
    key: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2dy1i+6iNAdFcPVNOG75KVMAM6J87Gnux1jtHJgFAFdbg3tySyWlWcXwwTHV7RRWOGhSpwY5Llqj5E29db2pG1RQ+Xb794ShN+3z+egMkAEbeX1wqG6WkkT35Wn8FJLLrbp6Bkv9QkJnsB87hJCfnmp9KNv5aj3eLlFx6W8y6vbn2JlE00AUnZbSvXOqo5bWDDWwESzw9u49VIm4EyqT1P5oJQBT/Ia/RDfhop5u4zuBxsRLo1W8KE/l7QtuazQWuVT+unj239t9be+HkIsBTTgdikIgnane6s7zd+4GKCYIdORDSptRzpkiLfBPGii0MpQ8QCm+AHAVguOEWqhM+w=="
    state: present

- name: Allow my user to have passwordless sudo
  become: yes
  lineinfile:
    dest: /etc/sudoers
    state: present
    regexp: "^ramon"
    line: "ramon ALL=(ALL) NOPASSWD: ALL"
    validate: visudo -cf %s

Adding the Role to a Playbook

Then I took that role and incorporated to a playbook called common. The idea is that this is something that would want to do to any server in the lab.

- hosts: all

  roles:
    - add_user
- hosts: all

  roles:
    - add_user

Adding the Hosts to a Group

Finally I created entries for my hosts and then added the newest ones to a that I could easily target for this common playbook run against:

worker1 ansible_host=x.x.x.x
worker2 ansible_host=x.x.x.x

rp1 ansible_host=x.x.x.x
rp2 ansible_host=x.x.x.x
rp3 ansible_host=x.x.x.x
rp4 ansible_host=x.x.x.x
rp5 ansible_host=x.x.x.x

[pi_workers]
rp[1:5]

Execute the Playbook

Now I am able to run the playbook (I ran it a few times before so I don’t expect changes) to make sure things are in the state that I expect:

ramon@royrig:~/code/Lab/ansible (master)$ ansible-playbook -u pi -k -i hosts -l pi_workers playbooks/common.yml
SSH password: 

PLAY [all] *********************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************
[WARNING]: Platform linux on host rp3 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [rp3]
[WARNING]: Platform linux on host rp2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [rp2]
[WARNING]: Platform linux on host rp5 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [rp5]
[WARNING]: Platform linux on host rp4 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [rp4]
[WARNING]: Platform linux on host rp1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [rp1]

TASK [add_user : Make sure my users is on the host] ****************************************************************************************************************************************************************
ok: [rp5]
ok: [rp4]
ok: [rp3]
ok: [rp2]
ok: [rp1]

TASK [add_user : Make sure to add my public key for ssh-key auth] **************************************************************************************************************************************************
ok: [rp3]
ok: [rp4]
ok: [rp5]
ok: [rp2]
ok: [rp1]

TASK [add_user : Allow my user to have passwordless sudo] **********************************************************************************************************************************************************
ok: [rp4]
ok: [rp3]
ok: [rp5]
ok: [rp2]
ok: [rp1]

PLAY RECAP *********************************************************************************************************************************************************************************************************
rp1                        : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rp2                        : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rp3                        : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rp4                        : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rp5                        : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

ramon@royrig:~/code/Lab/ansible (master)$ 

Trying It Out

If all went as expected then I should be able to ssh right to the host and then run a sudo command.

ramon@royrig:~/code/Lab/ansible (master)$ ssh rp2
The authenticity of host 'rp2 (x.x.x.x)' can't be established.
ECDSA key fingerprint is SHA256:yH0Zmu+BPxv+zWkdoKY1oYIxB4Xd93EdEoHIc2pO/xI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'rp2' (ECDSA) to the list of known hosts.
Linux rp2 5.10.17-v7+ #1403 SMP Mon Feb 22 11:29:51 GMT 2021 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.


Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.

ramon@rp2:~ $ sudo echo

ramon@rp2:~ $

Success!