Introduction

My blog runs inside a Docker container on a DigitalOcean Droplet. More precisely, I'm using a docker-compose service consisting of several Docker containers, one among them being a PostgreSQL container holding the database of my blog. Every now and then I manually create backups of that DB:

  1. I ssh into my droplet (=server)
  2. on the server, I enter the postgres container to create a dump of my DB in a folder that is bind mounted
  3. in a last step I rsync the dumped DB from the server onto my local PC.

I have wanted to automate these steps via a bash script ever since my first dump, but I never took the time to do so. Recently, I have started to use Ansible, a tool which is designed for executing commands on remote machines over ssh. So I figured the above use case would be perfectly suitable to implement it with Ansible.

However, in this post we will first set up an Ansible Inventory to save the IP address of the remote machine as a variable so we won't have to type the IP address everytime we execute an Ansible command. Yeah, I'm pretty lazy when it comes to repetitive tasks that can be easily automated :)

Optional: Setting up a development environment

All comands in this article were run from within a Docker container. Its corresponding Dockerfile as well as the source code of the Ansible inventory host file can be found on Bitbucket. You can clone my repo and build the image like so:

git clone https://reinka@bitbucket.org/reinka/blog.git && cd blog && cd ansible && docker build -t my-ansible-env .

You can then run and enter a bash console within the container like so:

docker run -it -v $PWD/../ansible:/workspace/ansible my-ansible-env  bash

This also bind mounts the checked out "ansible" folder into your container under /workspace/ansible:

root@6c70e7fa4e6c:/workspace# pwd
/workspace
root@6c70e7fa4e6c:/workspace# ll 
total 8
drwxr-xr-x 3 root root 4096 Oct 12 12:13 ./
drwxr-xr-x 1 root root 4096 Oct 12 12:13 ../
drwxr-xr-x 4 root root  128 Oct 12 12:10 ansible/

Setting up an INI-file in your Ansible Inventory

By default, Ansible looks up host names saved in the location /etc/ansible/hosts. However, you can specify a different inventory file using the -i <path> option on the command line.

Alternatively, you can also set the enviromental variable ANSIBLE_INVENTORY, a comma separated list of Ansible inventory sources. This will be the approach taken here.

In my case, I created an INI file called hosts under /workspace/ansible/inventory/hosts with the following content:

blog ansible_user=xxx ansible_host=xxx.xxx.xxx.xxx ansible_python_interpreter=/usr/bin/python3

where ansible_user corresponds to the user the ssh command will be executed with and host to the IP address of my server. I specified the ansible_python_interpreter to use Python 3, otherwise you might see a deprecation warning depending on the OS of your server.

In a next step, I export the ANSIBLE_INVENTORY variable like so:

$ export ANSIBLE_INVENTORY=/workspace/ansible/inventory

(I added this line to my ~/.bashrc so I don't have to do it everytime I start a new terminal).

We can now execute an Ansible ping command (using the --key-file flag since I turned off PasswordAuthentication on my remote server) from the terminal, given Ansible is installed:

$ ansible blog -m ping --key-file ~/.ssh/id_rsa
The authenticity of host 'xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx)' can't be established.
ECDSA key fingerprint is SHA256:OcjSyTS3k1TqBMtn66ODtT1pR2i3In+DCfMajbAXS/w.
Are you sure you want to continue connecting (yes/no)? yes
Enter passphrase for key '/root/.ssh/id_rsa':
blog | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

This will prompt you to enter the password of the private ssh key, as seen in the output, before reporting the status of the result.

Shell commands can be run like so:

$ ansible blog -m shell -a "ls -a" --key-file ~/.ssh/id_rsa
Enter passphrase for key '/root/.ssh/id_rsa':
blog | CHANGED | rc=0 >>
.
..
.Xauthority
.ansible
.bash_history
.bash_logout
.bashrc
.cache
.cloud-locale-test.skip
.config
.gitconfig
.lesshst
.nano
.profile
.ssh
.sudo_as_admin_successful
.viminfo
.virtualenvs
bin

Conclusion

In this article, we learned how to configure the IP address of a remote machine as a host name variable using Ansible's ANSIBLE_INVENTORY environmental variable, which allows to execute Ansible commands using the specified host name. We also executed a simple ping and shell command on the remote machine via Ansible.

In a next article, we will learn how to execute a DB dump inside a Docker container on a remote machine using Ansible.

Getagged mit:
ansible Tutorial
blog comments powered by Disqus