As I was working on being able to deploy to a Digital Ocean droplet for “development”, “test”, and “production”, I realized that my original vision of the Ansible playbooks needed some refinement.

First, rather than listing each server and a number of roles which build on each other like this:

- name: Lachlanlife Prod server
  hosts:
    - lachlanblog
  remote_user: ansible
  become: yes
  roles:
    - common
    - debian
    - fail2ban
    - sshkeys-root
    - ufw

It made more sense to utilize dependencies to define which roles are required to support the final role. For example, this blog runs on Ghost which requires Docker which runs on Debian.

Within the role directory, create a meta directory containing the default.yml file. This is what the ghost role would look like:

dependencies: 
  - role: docker

The docker role would contain the dependencies:

dependencies:
    - role: debian
    - role: common
    - role: fail2ban
    - role: sshkeys-root
    - role: ufw

The second enhancement was to separate the playbooks out by server environment rather than by hostingp provider. Previously, I had a playbook for all local hosts, one for Digital Ocean.

Instead, it made more sense to have one playbook for the “development” environment, the “production environment” which allows me to roll out changes and upgrades in stages.

Here is a small excerpt from the new Ansible playbooks directory structure.

dev.yml
prod.yml
bootstrap.yml
- inventory
  - group_vars
  - host_vars
    - lachlandev
- roles
  - docker
    - defaults
      - mail.yml
    - handlers
      - main.yml
    - tasks
      - main.yml
    - templates/etc
      - apt/preferences.d
        - docker.pref.j2
      - docker
        - daemon.json.j2
      - systemd/system/docker.service
        - custom.conf.j2
        - environment.conf.j2
        - options.conf.j2

In my next update, I will cover how I set up the e-mail server for lachlanlife.net using Mailcow on Docker.