Ansible - zbrewer/homelab GitHub Wiki
Ansible can be installed in Ubuntu using apt: sudo apt update && sudo apt install ansible
. A config directory, such as ~/ansible
should then be created and basic inventory
and ansible.cfg
files should be placed within it. For example, the following is a basic ansible.cfg
(paths should be replaced as necessary):
[defaults]
inventory = ~/ansible/inventory
private_key_file = ~/.ssh/id_ed25519
A basic inventory file might look like:
[group]
hostname ansible_user=username
If you are using a password-protected private key(s), it will need to be added to ssh-agent so that Ansible can use it reliably. The result of these steps is that, when running a playbook, you will be prompted for the password associated with your private key. The command will then run without re-prompting for the next hour (the key timeout can be changed in the ~/.bashrc
ssh-add
commands below.
The first step is to define a new systemd user service at ~/.config/systemd/user/ssh-agent.service
with the following contents:
[Unit]
Description=SSH key agent
[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
[Install]
WantedBy=default.target
This will cause the ssh-agent
to start automatically. In addition, the following will need to be appended to your ~/.bashrc
file (with the path to your private key updated as necessary):
# Setup ssh-add for Ansible so that private keys with passwords work correctly.
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
command -v ansible > /dev/null &&
alias ansible='ssh-add -l > /dev/null || ssh-add -t 1h ~/.ssh/id_ed25519 2> /dev/null && ansible'
command -v ansible-playbook > /dev/null &&
alias ansible-playbook='ssh-add -l > /dev/null || ssh-add -t 1h ~/.ssh/id_ed25519 2> /dev/null && ansible-playbook'
For hosts where Ansible isn't logging in as root (generally a good thing), you will need to tell it how to escalate its permissions so that it can perform management tasks (such as updates). This requires storing sudo passwords on the host running Ansible; however, a vault can be used to encrypt these so that they aren't stored in plain text.
In order to do this, navigate to your ~/ansible
directory and run ansible-vault create <vault_name>.yml
where <vault_name>
can be whatever you'd like the file to be called. It will ask you to create a passphrase for this vault (and to confirm) before opening an editor so that you can add contents. In general, this file will contain key/value pairs where the key is a variable name that can be referenced in Ansible config files and the value is the secret. For example, the file may look like:
---
my_first_secret: secret-value
another_secret: hidden-value
In order to edit this vault later, simply use the ansible-vault edit <vault_name>.yml
command and enter the vault password to be returned to the editor. This makes it easy to update as needed without managing a large number of additional keys or manually copying encrypted variable values into config files.
Once the vault has been set up, add the line ask_vault_pass = yes
under the [default]
header in your ansible.cfg
file. This will prompt ansible to automatically ask for your vault password when running ansible or ansible-playbook commands instead of having to remember to include the --ask-vault-pass
flag. This means that all commands, even those that don't need privilege escalation, will ask for the vault password (instead of just those where the flag is specified) which may be slightly inconvenient but I find that is means I have to remember fewer steps.
It should also be noted that var_files: <path_to_vault>
will need to be included in playbooks (outside of the tasks block) that need the variables. One-shot commands using the ansible
CLI will need to specify the variable file with the --extra-vars '@<path_to_vault>.yml'
flag. One of these approaches is needed in order to ensure that Ansible knows where to look for the variables.
Speaking of variables, in order for Ansible to know how to use sudo, the following host variables must be set up. This example shows YAML but the same approach works in INI files.
hosts:
name_of_host:
ansible_user: non_root_username
ansible_become_method: sudo
ansible_become_pass: "{{ password_variable_name_from_vault }}"
Playbooks can then specify become = yes
in order for hosts to sudo as necessary.
In order to see if your config is working and all hosts can be reached, use the ansible all -m ping
(ansible all --extra-vars '@<vault_path>.yml' -m ping
when using a vault) command from your ~/ansible
directory. This will try to connect to each host and should print a success message for each. If it does, they are all reachable and you are ready to move on.