Ansible: Difference between revisions

From Rixort Wiki
Jump to navigation Jump to search
No edit summary
 
(41 intermediate revisions by the same user not shown)
Line 8: Line 8:
Control machine requires Python 2.6 or later.
Control machine requires Python 2.6 or later.


Ansible is push-based, i.e. updates occur only when a playbook is run. However, pull-based support is available via `ansible-pull`.
Ansible is push-based, i.e. updates occur only when a playbook is run. However, pull-based support is available via <code>ansible-pull</code>.


No abstraction is available, so playbooks are OS and distribution specific (e.g. use `apt` for Debian).
No abstraction is available, so playbooks are OS and distribution specific (e.g. use <code>apt</code> for Debian).


Ansible runs each task in parallel across every host, and does not move on to the next task until all hosts have completed.
Ansible runs each task in parallel across every host, and does not move on to the next task until all hosts have completed.
Line 16: Line 16:
== Configuration file ==
== Configuration file ==


Ansible will look for an `ansible.cfg` file in the following locations:
Ansible will look for an <code>ansible.cfg</code> file in the following locations:


# Location specified by <code>ANSIBLE_CONFIG</code> configuration.
# Location specified by <code>ANSIBLE_CONFIG</code> configuration.
Line 32: Line 32:
  private_key_file = ~/.vagrant.d/insecure_private_key
  private_key_file = ~/.vagrant.d/insecure_private_key
  host_key_checking = False
  host_key_checking = False
== SSH options ==
Accelerated mode makes an initial SSH connection and then sends further commands via port 5099. To use this:
* Install <code>python-keyczar</code>
* Add <code>accelerate: true</code> at the top level of the playbook
There are some problems using accelerated mode with <code>sudo</code>, which requires additional configuration.
Port 5099 must of course be allowed through the firewall.


== Command module ==
== Command module ==
Line 63: Line 74:


The <code>sudo</code> option in a playbook means that every task should be run via <code>sudo</code>. This is particularly useful on Ubuntu servers, and also on servers where root SSH login has been disabled.
The <code>sudo</code> option in a playbook means that every task should be run via <code>sudo</code>. This is particularly useful on Ubuntu servers, and also on servers where root SSH login has been disabled.
All tasks in a playbook can be listed by running:
<code>ansible-playbook --list-tasks playbook.yml</code>


== Handlers ==
== Handlers ==
Line 70: Line 85:
  handlers:
  handlers:
     - name: restart apache
     - name: restart apache
       service: name=apache2 state=restarted
       service:
        name: apache2
        state: restarted


This will run if a task includes:
This will run if a task includes:
Line 76: Line 93:
  notify: restart apache
  notify: restart apache


Handlers run after all tasks, and only run once regardless of how many times they are notified.
Handlers run after all tasks, and only run once regardless of how many times they are notified. Handlers are run in the order they are defined, not the order they are notified.


== File conventions ==
== File conventions ==
Line 82: Line 99:
* Support files (e.g. configuration) in: <code>files</code>
* Support files (e.g. configuration) in: <code>files</code>
* Template files in: <code>templates</code>
* Template files in: <code>templates</code>
== Roles ==
Each Ansible role has a name, e.g. <code>web</code>. Files associated with this role go into <code>roles/web</code>, including:
* <code>tasks/main.yml</code> - tasks
* <code>files/</code> - files, as per usual Ansible layout
* <code>templates/</code> - Jinja2 templates
* <code>handlers/main.yml</code> - handlers
* <code>defaults/main.yml</code> - default variables than can be overridden.
The file structure can be automatically created using:
<code>ansible-galaxy init base</code>
The above command will create a file structure for a role called <code>base</code> in the current directory.
A playbook may contain multiple roles, and variables for each role can be overridden on a per-play basis.
Tasks can be run before or after roles are applied.
When using a <code>template</code> directive within a role, Ansible will look for the file in the <code>templates/</code> subdirectory, unlike in top-level playbooks where you need to specify the full path (i.e. <code>templates/file.j2</code>).
=== Base server ===
Packages that should be installed on a basic server:
* OpenSSH
* UFW - firewall rules
* SSHGuard - automatically block dictionary attacks etc. Is this still the best option? fail2ban?
* vnstat - monitor total amount of network traffic
* Postfix - for outgoing email (e.g. notifications)
* Monit - basic monitoring, might want to swap out for something more sophisticated. At a bare minimum we need to monitor the disk space and any services.
* NTP - for time synchronisation (no longer required as Ubuntu ships with timesyncd, part of systemd)
* <code>unattended-upgrades</code>
* Backup scripts
* certbot / dehydrated
==== General ====
* Set hostname and mailname before installing packages
Disabling MOTD updates for privacy reasons:
In file:
/etc/default/motd-news
set:
ENABLED=0
==== certbot ====
* How do we get around the bootstrapping problem when obtaining a certificate for the first time? DNS challenge?
* Is a recent version of dehydrated available in the Ubuntu repositories, or a PPA?
* May also need certificates for email and other services
* Do we need a cron job to reload services after certificates have been renewed?
* Should DNS challenge and dehydrated be in a separate Mythic Beasts role?
==== Automatic blocking ====
* Need to block based on: SSH, web, SMTP
==== Postfix ====
Configuration options:
* Strong cipher suites
* Always attempt TLS on outgoing connections
==== UFW ====
* Deny all incoming apart from ping (default?) and SSH
* Allow all outgoing
* Log all blocked connections
==== Monit ====
* Specify email address for reports
* Create template for monit configuration file so we can pass in multiple services and variables such as disk space
==== unattended-upgrades ====
* Configure to apply all updates, not just security ones
* Specify email address for reports
=== Web server ===
* Nginx
* PHP FPM
=== Database server ===
* MariaDB - usually <code>mariadb-server</code> and <code>mariadb-client</code>
* MySQL-python - <code>python3-mysqldb</code>
* Set root password to a random value?
* MySQL backups
=== Role dependencies ===
Roles can depend on other roles. Dependencies are specified in <code>meta/main.yml</code>, for example:
<pre>
dependencies:
  - role: base
    vars:
      install_packages:
        - nginx
</pre>
=== Example roles ===
* https://git.coop/webarch/fail2ban
* https://git.coop/webarch/exim
== Testing ==
The official testing framework for Ansible roles is [https://molecule.readthedocs.io/ Molecule].
== Links ==
* [https://www.ansible.com/infrastructure-testing-with-molecule Infrastructure testing with Molecule] - Talk from Ansiblefest 2017.
* [https://zapier.com/engineering/ansible-molecule/ How We Test Our Ansible Roles with Molecule]
* [https://www.jeffgeerling.com/blog/2018/testing-your-ansible-roles-molecule Testing your Ansible roles with Molecule]
* [https://www.ansiblefordevops.com/ Ansible for DevOps]
* [https://jpmens.net/2019/12/11/on-building-an-ansible-training-environment-on-freebsd/ On building an Ansible training environment on FreeBSD]

Latest revision as of 11:28, 25 July 2020

Requirements

Requirements on hosts:

  • SSH
  • Python 2.5 or later

Control machine requires Python 2.6 or later.

Ansible is push-based, i.e. updates occur only when a playbook is run. However, pull-based support is available via ansible-pull.

No abstraction is available, so playbooks are OS and distribution specific (e.g. use apt for Debian).

Ansible runs each task in parallel across every host, and does not move on to the next task until all hosts have completed.

Configuration file

Ansible will look for an ansible.cfg file in the following locations:

  1. Location specified by ANSIBLE_CONFIG configuration.
  2. ./ansible.cfg
  3. ~/.ansible.cfg
  4. /etc/ansible/ansible.cfg

Placing the file in the current directory alongside playbooks is the easiest solution, and keeps everything together.

Sample configuration file:

[defaults]
hostfile = hosts
remote_user = vagrant
private_key_file = ~/.vagrant.d/insecure_private_key
host_key_checking = False

SSH options

Accelerated mode makes an initial SSH connection and then sends further commands via port 5099. To use this:

  • Install python-keyczar
  • Add accelerate: true at the top level of the playbook

There are some problems using accelerated mode with sudo, which requires additional configuration.

Port 5099 must of course be allowed through the firewall.

Command module

Arbitrary commands can be executed using the command module:

ansible hostname -m command -a uptime

Passing -s runs the command as root, using sudo.

Update packages:

ansible hostname -s -m apt -a "update_cache=yes"

Install package:

ansible hostname -s -m apt -a "name=apache2"

Restarting service:

ansible hostname -s -m service -a "name=apache2 state=restarted"

Playbooks

Playbooks are YAML files which contain tasks to be run on a group of hosts. Each playbook must contain:

  • A list of hosts.
  • A list of tasks to be run on the hosts.

Command: ansible-playbook playbook.yml

The sudo option in a playbook means that every task should be run via sudo. This is particularly useful on Ubuntu servers, and also on servers where root SSH login has been disabled.

All tasks in a playbook can be listed by running:

ansible-playbook --list-tasks playbook.yml

Handlers

Handlers are similar to tasks, but they only run if notified. An example handler might be:

handlers:
    - name: restart apache
      service:
        name: apache2
        state: restarted

This will run if a task includes:

notify: restart apache

Handlers run after all tasks, and only run once regardless of how many times they are notified. Handlers are run in the order they are defined, not the order they are notified.

File conventions

  • Support files (e.g. configuration) in: files
  • Template files in: templates

Roles

Each Ansible role has a name, e.g. web. Files associated with this role go into roles/web, including:

  • tasks/main.yml - tasks
  • files/ - files, as per usual Ansible layout
  • templates/ - Jinja2 templates
  • handlers/main.yml - handlers
  • defaults/main.yml - default variables than can be overridden.

The file structure can be automatically created using:

ansible-galaxy init base

The above command will create a file structure for a role called base in the current directory.

A playbook may contain multiple roles, and variables for each role can be overridden on a per-play basis.

Tasks can be run before or after roles are applied.

When using a template directive within a role, Ansible will look for the file in the templates/ subdirectory, unlike in top-level playbooks where you need to specify the full path (i.e. templates/file.j2).

Base server

Packages that should be installed on a basic server:

  • OpenSSH
  • UFW - firewall rules
  • SSHGuard - automatically block dictionary attacks etc. Is this still the best option? fail2ban?
  • vnstat - monitor total amount of network traffic
  • Postfix - for outgoing email (e.g. notifications)
  • Monit - basic monitoring, might want to swap out for something more sophisticated. At a bare minimum we need to monitor the disk space and any services.
  • NTP - for time synchronisation (no longer required as Ubuntu ships with timesyncd, part of systemd)
  • unattended-upgrades
  • Backup scripts
  • certbot / dehydrated

General

  • Set hostname and mailname before installing packages

Disabling MOTD updates for privacy reasons:

In file:

/etc/default/motd-news

set:

ENABLED=0

certbot

  • How do we get around the bootstrapping problem when obtaining a certificate for the first time? DNS challenge?
  • Is a recent version of dehydrated available in the Ubuntu repositories, or a PPA?
  • May also need certificates for email and other services
  • Do we need a cron job to reload services after certificates have been renewed?
  • Should DNS challenge and dehydrated be in a separate Mythic Beasts role?

Automatic blocking

  • Need to block based on: SSH, web, SMTP

Postfix

Configuration options:

  • Strong cipher suites
  • Always attempt TLS on outgoing connections

UFW

  • Deny all incoming apart from ping (default?) and SSH
  • Allow all outgoing
  • Log all blocked connections

Monit

  • Specify email address for reports
  • Create template for monit configuration file so we can pass in multiple services and variables such as disk space

unattended-upgrades

  • Configure to apply all updates, not just security ones
  • Specify email address for reports

Web server

  • Nginx
  • PHP FPM

Database server

  • MariaDB - usually mariadb-server and mariadb-client
  • MySQL-python - python3-mysqldb
  • Set root password to a random value?
  • MySQL backups

Role dependencies

Roles can depend on other roles. Dependencies are specified in meta/main.yml, for example:

dependencies:
  - role: base
    vars:
      install_packages:
        - nginx

Example roles

Testing

The official testing framework for Ansible roles is Molecule.

Links