####### Ansible ####### Ansible is an open-source automation tool. What that means is that you can use ansible to automatically do everything that you would normally do yourself on the server with the benefit that there is - no repetition - you write down what you want to do and ansible does it - to 1 or 100 servers - you don't forget what you did Ansible typically runs on your local computer and carries out tasks on a remote server. Ansible uses simple, human-readable scripts called playbooks to automate your tasks. So your job is to describe the state which a server should have - ansible will log into the system via SSH and ensures this state. In this guide we will develop some examples so that you can get a feel of what the things above really mean. .. warning:: This guid will not help you install ansible. If you are on linux you can follow the `official documentation `_. On Windows you either should use `WSL `_ (recommended) or you can `try to run it using docker `_. You could also run the playbook from the server itself. Please discuss this with an administrator. Basics ====== Let's use ansible for the first time and learn the basic building blocks. Let's make a quick introduction. * :code:`tasks`: These are (this might come as a surprise) tasks ansible will complete. An example of a task is: "Ensure that the directory XYZ exists" or "Restart the service ssh.service". There is a wide variety of pre-made tasks to choose from * :code:`vars`: Variables that you can use to define values, e.g. the name of a directory that should be created. Variables are defined per-host or per group of hosts * :code:`hosts`: The servers that ansible will control. Hello World =========== Now we take what we learned and create a directory and file on our server. The file will be located at :file:`/tmp/ansible_testing/hello_world`. Put the following code (your first ansible playbook) in a file called :file:`ansible-1.yml` .. code-block:: yaml - hosts: all vars: base_directory: "/tmp/ansible_testing" tasks: - file: path="{{ base_directory }}" mode=0700 state=directory - file: path="{{ base_directory }}/hello_world" mode=0600 state=touch You see two :code:`file` tasks there. The first one creates the direcotry :file:`/tmp/ansible_testing/`, the second creates the file :file:`hello_world` in there. The directory location is here defined as variable. We can access this variable with the double-bracket syntax :code:`{{ var_name }}`. This will evaluate to :code:`/tmp/ansible_testing`. We also need to tell ansible on which server these tasks should be executed. We use a inventory file for that. Create a file called :code:`hosts` with the following content. .. code-block:: intern.queereszentrumtuebingen.de ansible_user=root If you created both files you can now execute the your first playbook with the :program:`ansible-playbook` command! .. code-block:: ansible-playbook -i hosts --private-key=~/.ssh/KEY_NAME ansible-1.yml - :code:`-i hosts` is used to point the :program:`ansible-playbook` command to the inventory file - :code:`--private-key=~/.ssh/KEY_NAME` defines where your SSH key to the server is located - :code:`ansible-1.yml` is the playbook file You can then verify that the file is correctly created on the server by logging in and executing .. code-block:: $ ls /tmp/ansible_testing hello_world Playbook structure ================== Most ansible roles are a lot more complex than our short hello_world. Therefor we will use a new structure of playbooks that will help you keep track of things. A typicall playbook will have these parts: * :code:`inventory` This is where we will define our hosts and the host_vars. * :code:`roles` this directory has one or more roles that collect the tasks that will be executed * :code:`setup.yml` this file will list all roles that should be executed for given server groups The following is an example of a playbook. There are two hosts defined (``qz1`` and ``qz2``) with their respective :file:`vars.yml`. There is only a single role called static-server which itself has various tasks attatched to it. :file:`LICENSE` and :file:`README.md` provide additional information on the playbook. .. code-block:: . ├── inventory │ ├── hosts │ └── host_vars │ ├── qz1.queereszentrumtuebingen.de │ │ └── vars.yml │ └── qz2.queereszentrumtuebingen.de │ └── vars.yml ├── LICENSE ├── README.md ├── roles │ └── static-server │ ├── defaults │ │ └── main.yml │ ├── tasks │ │ ├── install.yml │ │ ├── main.yml │ │ ├── setup_site.yml │ │ ├── uninstall.yml │ │ └── validate_config.yml │ └── templates │ └── docker-compose.yml.j2 └── setup.yml The :file:`setup.yml` for this playbook could look like this. .. code-block:: yaml - name: "Set up a static server" hosts: "static_site_servers" become: true roles: - role: roles/static-server and the :file:`inventory/hosts` like this .. code-block:: yaml [static_site_servers] qz1.queereszentrumtuebingen.de ansible_user=root qz2.queereszentrumtuebingen.de ansible_user=root There are a lot of examples which you can use as inspiration for playbooks. Here are some listed from easy to hard to understand * `moanos/ansible-playbook-static-site-host `_: The example used above that set's up a structure for a simple static site server. * `moan0s/ansible-playbook-borgbackup-host `_: A similar playbook that set's up a borgbackup host (place to store backups). We use this for our backup servers. * `mother-of-all-self-hosting/mash-playbook `_: A somewhat complex playook that the QZT uses to set up most services * `spantaleev/matrix-docker-ansible-deploy `_: A complex playook to set up a matrix server