Once you have a list of hosts (see [Terraform server setup](./03_Terraform%20server%20setup.md)), you can start working on the Ansible plays.

# Prerequisites
Before running the Ansible plays, a few things need to be generated or updated first.

## General

- Extract the SSH key to log into the VMs from Terraform. Running `../tools/get_ssh_key.sh` in the `terraform` directory should extract it from the tfstate file, generating the file `vm_ssh_key`. Copy this key to the `ansible` directory, and run `chmod 0600 vm_ssh_key`.

- Generate student_data.json using `tools/generate_group_data.py` (working dir should be the root folder; this requires `student_groups.csv` and `ta_groups.csv`)

- Generate the Ansible inventory with `generate_inventory.sh`

- Generate the host variables with `generate_host_vars.py`. This generates:
	- `pma_blowfish`: used for phpmyadmin, just a random string
	- `mysql_root_password`: password for the MySQL root account
	- `domain_name`: xxx.webtech-uva.nl, generated from group name
	- `users`: list of user objects
		- user objects have name, mysql_password
		- taken from generated `student_data.json`, adds mysql_password

- Update the bundled phpMyAdmin in `templates/phpmyadmin`
- Update course year in `group_vars/servers`

## DNS

You should be able to see the domain `webtech-uva.nl` through [Azure Portal](https://portal.azure.com/). Each group should have its own subdomain: `{groupname}.webtech-uva.nl` (e.g. `in01.webtech-uva.nl`); these point to the server assigned to the group.

The easiest way to set these up is to use some sort of Azure CLI tool and use the group to IP mapping that is generated by `tools/get_groupnames.sh`.

For instance, using `azure-cli`:

- Log in using `az login`
- To create an A DNS record, use `az network dns record-set A add-record -g webtech -z webtech-uva.nl -n <subdomain> -a <ip>`

A script automating this for all groups in `groupnames.json` can be found in `tools/create_dns_entries.sh`.

There is a similar script which sets up SPF entries for the mail server.

## SSL

As mentioned above, SSL is done using LetsEncrypt. Since we control the DNS, the easiest and reasonably safe method is to just generate one wildcard certificate and install it on all of the different servers.

LetsEncrypt has an Azure plugin, but using it requires creating things in Azure that we do not have access to, so at this point we just use a manual DNS challenge. Given that this is a single certificate, that's not too bad. In previous years, I have used a tool called `dehydrated` for this purpose; it is included in the `dehydrated/` directory. It is a simple ACME client which allows us to use a custom hook script to request certificates.

To request a certificate, use the following command:

`./dehydrated -c --challenge dns-01 --hook ./hook.sh --domains-txt ./domains.txt`

This uses the hook script `hook.sh` and requests certificates for the domains specified in `domains.txt`. The certificates can then be found in the `certs` directory. Copy the `webtech-uva` directory to `ansible/templates/ssl`.

# Running the Ansible plays
After handling the prerequisites, you should be able to run the Ansible plays, using `ansible-playbook plays/<play>.yaml`.

Play `11-nginx` is an experimental nginx setup; it is not enabled by default (so you can safely run the play) but it is also not required.

Play `14-zabbix` is optional, and requires the setup of a separate Zabbix server, for monitoring. This doesn't have documentation yet (sorry!); some of the plays for provisioning the Zabbix server are in the `zabbix_server/` subdirectory.
Occasionally, things go wrong, and so there are various fixup plays, starting with 9999. These are not required.
