Ansible playbook and SSH keys
Tags: ansible, devops, tutorial
Published: 2023-06-13 21:11:31

## Introduction 

Last time ([LINK](https://dev.to/rimelek/the-first-ansible-playbook-579h)) we configured a very simple Ansible playbook, and we used password authentication instead of SSH keys. That was easy, except the fact that macOS didn't support the requirements, so I had to run a Linux virtual machine as Ansible controller.

The problem with passwords is that not all servers allow password authentication for security reasons and the way we did it last time, we had to type the password every time we ran the playbook. Not to mention if someone finds out your password they can access your server even if they don't have access to your workstation where your SSH keys are.

You can also watch the video about this on YouTube

{% embed https://youtu.be/T3XW0YcbNaw %}

## Table of contents

- [Before you begin](#before-you-begin)
  - [Requirements](#requirements)
  - [Download the already written code of the previous episode](#download-the-already-written-code-of-the-previous-episode)
  - [Have an inventory file](#have-the-inventory-file)
  - [Activate the Python virtual environment](#activate-the-python-virtual-environment)
- [Generate an SSH key](#generate-an-ssh-key)
- [Install the SSH public key on the remote server](#install-the-ssh-public-key-on-the-remote-server)
- [Configure Ansible to use SSH private key](#configure-ansible-to-use-the-ssh-private-key)
- [SSH key without a passphrase](#ssh-key-without-a-passphrase)
- [Conclusion](#conclusion)

## Before you begin

### Requirements

[» Back to table of contents «](#table-of-contents)

- The project requires Python 3.11. If you have an older version and you don't know how you could install a new version, read about Nix in [Install Ansible 8 on Ubuntu 20.04 LTS using Nix](https://dev.to/rimelek/install-ansible-8-on-ubuntu-2004-lts-using-nix-46hm)
- You will also need to create a virtual Python environment. In this tutorial I used the "venv" Python module and the name of the folder of the virtual environment will be "venv".
- You will also need an Ubuntu remote server. I recommend an Ubuntu 22.04 virtual machine.

### Download the already written code of the previous episode

[» Back to table of contents «](#table-of-contents)

If you started the tutorial with this episode, clone the project from GitHub:

```bash
git clone https://github.com/rimelek/homelab.git
cd homelab
```

If you cloned the project now, or you want to make sure you are using the exact same code I did, switch to the previous episode in a new branch

```bash
git checkout -b tutorial.episode.1b tutorial.episode.1
```

### Have the inventory file

[» Back to table of contents «](#table-of-contents)

Copy the inventory template

```bash
cp inventory-example.yml inventory.yml
```

And change `ansible_host` to the IP address of your Ubuntu server that you use for this tutorial, and change `ansible_user` to the username on the remote server that Ansible can use to log in.

### Activate the Python virtual environment

[» Back to table of contents «](#table-of-contents)

How you activate the virtual environment, depends on how you created it. The [previous episode](https://dev.to/rimelek/the-first-ansible-playbook-579h#install-ansible) describes the way to create and activate the virtual environment using the "venv" Python module. 

For example:

```yaml
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

## Generate an SSH key

[» Back to table of contents «](#table-of-contents)

First you need to generate an SSH key pair, install the public key on the remote server and configure the private key on the ansible controller. The simple command to generate an SSH key would be

```bash
ssh-keygen
```

and pressing enter without providing any passphrase. If you have many SSH keys, you might want to set a custom path for the key, and you can also change the default algorithm.

```bash
ssh-keygen -f ~/.ssh/ansible -t ed25519
```

When it asks for a passphrase, you can leave it empty or set it to protect your SSH key. Since not using passphrase would be too easy, we will use it and follow the recommendations of the Ansible documentation.

## Install the SSH public key on the remote server

[» Back to table of contents «](#table-of-contents)

You need to install the public key on the remote server. 

```bash
ssh-copy-id -i ~/.ssh/ansible.pub ta@192.168.4.58
```

All you need to pass are the path of the public key and the connection string. Since I have no client configuration yet, I passed the username and IP address as well in the connection string. Depending on the chosen algorithm, you would see something like this on the remote server in `$HOME/.ssh/authorized_keys`

```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICc/6Mhk0/yj1mpJPw0rMpgbp/2Dev7oieSTuj8/6LvJ ubuntu@ansible-controller
```

## Configure Ansible to use the SSH private key

[» Back to table of contents «](#table-of-contents)

You need to set the path of the SSH private key in the inventory file:

```yaml
ansible_ssh_private_key_file: ~/.ssh/ansible
```

So the final inventory file would look like this:

```yaml
all:
  vars:
    ansible_user: ta
  hosts:
    ta-lxlt:
      ansible_host: 192.168.4.58
      ansible_ssh_private_key_file: ~/.ssh/ansible
```

Don't forget to activate your virtual python environment if you have one (see my [previous post](https://dev.to/rimelek/the-first-ansible-playbook-579h))

If you run the playbook now, it will still ask for the passphrase.

```bash
ansible-playbook -i inventory.yml playbook.yml
```

Output:
```
PLAY [Play 1] ************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************
Enter passphrase for key '/home/ubuntu/.ssh/ansible':
```

Type the passphrase, press enter, wait for the playbook to be finished and run in again. It might not ask for the passphrase again if you do it quickly enough, although, if you use the same key with a simple ssh command from the terminal you will probably get a passphrase prompt every time. Since you don't always run playbooks so quickly, you can follow Ansible's documentation [and configure the SSH agent](https://docs.ansible.com/ansible/latest/inventory_guide/connection_details.html#setting-up-ssh-keys).

```bash
ssh-agent $SHELL
ssh-add ~/.ssh/ansible
```

Since it starts a new bash shell, the name of the virtual environment will disappear from your prompt. If you want it back, you need to activate the virtual environment again, but the ansible commands would work without it.

The `ssh-add` command will ask for the passphrase, and you can run the playbook again without the passphrase prompt.

```bash
ansible-playbook -i inventory.yml playbook.yml
```

And that's not all. You can also use a simple SSH command like below to use the added ssh key and log in to your remote server without a passphrase:

```bash
ssh ta@192.168.4.58
```

## SSH key without a passphrase

[» Back to table of contents «](#table-of-contents)

Since my goal is to help you create a local environment for testing and learning, if you feel the previous solution was too complicated for you to log in to a sandbox virtual machine, you can also choose not to set a passphrase when you generate the key. Adding a configuration to your `$HOME/.ssh/config` file like below could be enough for a simple SSH command too:

```
Host 192.168.4.58
  IdentityFile ~/.ssh/ansible
```

This is actually what I use for my local virtual machines and  if you try to find out how multipass lets you get a shell in the virtual machine, you will find out it has an SSH key and you in fact use SSH connection when you run `multipass shell VM_NAME`

## Conclusion

[» Back to table of contents «](#table-of-contents)

In this post I wanted to focus on the SSH keys, so you can start to use it. There are different ways for different environments, and you need to decide what is more important. Security or convenience. Of course if you are building your home lab for learning, you might want to learn about security as well, but you don't necessarily have to start with that. Later, when you really need to use more secrets, passwords in your Ansible playbooks, you will use some encrypted configuration files too, however, if you try to start with the most secure configuration which can also work in a production environment you might give up without having enough motivation to invest more time in security.

Keep that in mind and your (professional) life will be easier with Ansible, not harder.

The final source code of this episode can be found on GitHub:

<https://github.com/rimelek/homelab/tree/tutorial.episode.2>

{% embed https://github.com/rimelek/homelab %}