ansible-mail-infra
Set up infrastructure for all things e-mail
Prep
On your Ansible controller make sure the sshpass
binary exists if Ansible has to connect to target machines via SSH username-password authentication instead of SSH key authentication. The binary usually comes with a package of the same name.
We're assuming that you're running Ansible as a Python package inside a virtual environment. Install Ansible like so:
pip install ansible
We're also assuming that secrets are stored in a HashiCorp Vault instance to which you have access. These roles access Vault via hvac
, the HashiCorp Vault API client for Python 3.x, see github.com/hvac/hvac for reference. Install it like so:
pip install hvac
Vars
-
For default variables copy ansible/roles/20-common-20-ssh/defaults/main.yml.example to a proper
ansible/roles/20-common-20-ssh/defaults/main.yml
, adjust as needed. -
Create your inventory, copy ansible/hosts.yml.example to a proper
ansible/hosts.yml
file with at least one host in host groupall
. -
Replace ansible/group_vars/all/vars.yml.example with a proper
ansible/group_vars/all/vars.yml
file and set at leastansible_user
and Vault access variables. -
In ansible/roles/20-common-20-ssh/files/root/.ssh copy both authorized_keys.example and known_hosts.example to proper files. They contain SSH authorized_keys and public SSH host keys you want installed on target machines.
Vault structure
In Vault we're assuming that every host in your inventory has a secret stored that contains at least the following keys:
initial_password
: The operating system's local account password at machine creation. Ansible will use this to SSH into the machine duringfirst_run
, see section Run it below.password
: The new password you want to set for the operating system's local account.password_salt
: The salt you're going to use. We're hashing the password with SHA-512, the salt is a string of up to 16 characters length.
For an example server fully.qualified.domain.name
and example user root
Vault secrets are located at name/domain/qualified/fully/os/root/creds
. Per ansible/group_vars/all/vars.yml.example the default secrets engine mount point is kv
where this playbook expects a kv secrets engine.
Run it
On first run execute it like so:
ansible-playbook --tags 'first_run' --inventory hosts.yml playbook.yml
The first_run
tag ensures that ansible_password
variable gets set which in turn causes Ansible to log in to target machines via SSH username-password authentication.
On subsequent runs like so:
ansible-playbook --inventory hosts.yml playbook.yml
first_run
To make sure a first_run
correctly runs all regular tasks plus first_run
-specific tasks ansible/roles/20-common-20-ssh/tasks/main.yml has its import_tasks
tagged as first_run
.
- import_tasks: '20-ssh.yml'
tags:
- 'first_run'
As a result all tasks in that import inherit first_run
. Two of them, however, must only run during first_run
and never during normal operation. They get:
- name: '...'
tags:
- 'first_run'
- 'never'
This overrides the single first_run
inherited tag. Ansible special tag never
ensures that these particular tasks are never executed unless first_run
is called. Tasks outside of 20-common-20-ssh
role are not tagged with first_run
at all so are ignored during a first_run
.