Skip to content

Ansible Structure

Osotechie edited this page Jun 22, 2026 · 1 revision

Ansible Structure

This page explains how the Ansible configuration is organised and how the different files relate to each other.

🔗 If you're new to Ansible, check out the official getting started guide. This page focuses on my setup, not Ansible basics.

Directory Layout

ansible/
├── ansible.cfg                    # Ansible configuration
├── inventory/
│   ├── environments.yml           # Host definitions (test + production)
│   └── group_vars/
│       ├── production.yml         # Variables for production NAS
│       └── test.yml               # Variables for test NAS
└── playbooks/
    ├── provision.yml              # Main provisioning playbook
    ├── updates.yml                # OS update + reboot playbook
    └── roles/
        ├── owendemooy.docker/
        ├── owendemooy.storage/
        ├── owendemooy.samba/
        ├── owendemooy.nut-client/
        ├── owendemooy.nas-backup/
        └── owendemooy.coraltpu/

Configuration (ansible.cfg)

[defaults]
inventory = inventory/environments.yml
roles_path = playbooks/roles/
host_key_checking = False
  • inventory — points to the environments file so we don't have to pass -i every time
  • roles_path — tells Ansible where to find our custom roles
  • host_key_checking = False — disabled here because we handle host key verification at the SSH level in the GitHub Actions workflow (see Network & Connectivity)

Inventory (environments.yml)

Defines two environments with their connection details:

test:
  hosts:
    nas-build-test:
      ansible_host: 10.1.1.118
      ansible_user: owen

production:
  hosts:
    nas:
      ansible_host: 10.1.1.118 #currently the same as test (WIP)
      ansible_user: owen

The workflow uses --limit ${{ vars.ENV_NAME }} to target the correct environment during each matrix run.

Group Variables

The group_vars/ files contain all the configuration that drives the roles. Both test and production currently share the same structure (with different secrets injected at runtime via #{TOKEN}# patterns).

Key sections in the group_vars:

Section Purpose
functions List of roles to apply (controls which roles are conditionally included)
apt_packages Additional OS packages to install
users User accounts to create with SSH keys and group memberships
host_directories Directories to create with ownership and ACL permissions
samba_* Samba user and share configuration
storage_* Disk mounts and MergerFS pool definition
nut_client_* UPS monitoring configuration

💡 The functions list is the key toggle mechanism. Adding or removing a function name controls whether its corresponding role runs during provisioning.

Roles

Each role follows Ansible's standard role structure:

owendemooy.rolename/
├── defaults/main.yml    # Default variables (overridable)
├── tasks/main.yml       # The actual work
├── handlers/main.yml    # Service restart handlers (where needed)
├── files/               # Static files to copy
└── meta/main.yml        # Role metadata and dependencies

See individual role pages for details:

How Roles Are Applied

In provision.yml, roles are conditionally included based on the functions variable:

- name: Docker
  ansible.builtin.include_role:
    name: owendemooy.docker
  when: "'docker' in functions"

This means you can disable a role for a specific environment by simply removing it from the functions list in that environment's group_vars — no code changes to the playbook itself.

Clone this wiki locally