Now that I am separating my services into containers or even VMs, I have enough servers running that setting them all up for something new (like centralized log collection through syslog or updating their postfix configuration to point to a central mail relay) is becoming tedious to do manually or with ad-hoc scripts.
Enter Ansible – Ansible is a way to describe workflows as a YAML file and run them across a bunch of machines. It comes with a bunch of supported items like making sure a specific package is installed or install it if it isn’t, creating user accounts and assigning them to specific groups, templatizing and replacing contents in config files etc.
While this post is not going to cover how to use Ansible (there a lot of great tutorials out there), I wanted to cover one tip that helped me manage my heterogenous and bespoke server setup where the passwords are different for different servers. Ansible essentially will run the template on each machine and in most cases, you want Ansible to execute as root through sudo (for installing packages or adding users or making modifications to config files). In my case, my servers have a SSH key setup that allows my main Linux desktop to connect to them without a password as a regular user. This works great for Ansible, but the problem is when Ansible needs to execute a command through sudo
– Ansible supports this through a concept of become_pass
.
An easy way to handle different machines with different passwords to be used for sudo
is to create an ansible vault and put it under group_vars/all
folder (so something like ansible-vault create group_vars/all/vaulted_vars.yml
). In this file, we setup the machine specific passwords:
server1_become_pass: server1_password
server2_become_pass: server2_password
server3_become_pass: server3_password
Since we use ansible-vault, this file will be encrypted and will require your vault password to decrypt and be used, so you don’t have to worry about the passwords being stored in plaintext in the event of a compromise.
Now, your inventory file that has the list of hosts (say hosts.ini) can be specified like this:
[all]
server1 ansible_become_pass='{{ server1_become_pass }}'
server2 ansible_become_pass='{{ server2_become_pass }}'
server3 ansible_become_pass='{{ server3_become_pass }}'
Now when you refer to - hosts: all
, if you specify become: yes
, Ansible will get the password to use from the vault automatically for each host. Note that trying to do this vars file that were included in tasks or pre_tasks did not work as the inventory parsing is done before any tasks, so at least with my limited chatgpt infused understanding of Ansible, this seems to be the way to handle different host specific passwords in a straightforward manner.