Ansible Conventions and Best Practices
Conventions and best practices for authoring maintainable Ansible playbooks and roles.
Ansible Conventions and Best Practices
CRITICAL: General Rules
| REQUIRED Practice | PROHIBITED Practice |
|---|---|
| Use version control for ALL configs | Untracked playbooks |
| Use FQCN for modules | Short module names |
| Use idempotent modules | Raw shell commands |
| Give every task a name | Anonymous tasks |
| Use dynamic inventory | Static host lists |
REQUIRED: Task Naming Conventions
You MUST follow these naming rules:
| Rule | Example | NEVER Do |
|---|---|---|
| Start with action verb | "Install nginx" | "nginx installation" |
| Capitalize first letter | "Configure firewall" | "configure firewall" |
| Omit trailing periods | "Copy config file" | "Copy config file." |
| Omit role name from role tasks | "Start service" | "nginx : Start service" |
REQUIRED: Module Selection
| Scenario | MUST Use | NEVER Use |
|---|---|---|
| Package management | ansible.builtin.package | shell: apt install |
| Service management | ansible.builtin.service | command: systemctl |
| File operations | ansible.builtin.copy/template | shell: cp |
| User management | ansible.builtin.user | command: useradd |
When shell/command is unavoidable, you MUST:
- name: Build application from source
ansible.builtin.command:
cmd: make install
chdir: /opt/app
creates: /opt/app/bin/app # REQUIRED for idempotency
REQUIRED: Privilege Escalation Rules
| Context | MUST Do | NEVER Do |
|---|---|---|
| Most tasks need root | Set become: true at play level | Set on every task |
| Few tasks need root | Set become: true per task | Set at play level |
| No root needed | Omit become entirely | Set become: false |
REQUIRED: Secret Management
Ansible Vault Workflow
You MUST follow this exact process:
| Step | Action | File |
|---|---|---|
| 1 | Create group subdirectory | group_vars/<group>/ |
| 2 | Define all variables | group_vars/<group>/vars |
| 3 | Copy sensitive vars with prefix | group_vars/<group>/vault |
| 4 | Reference vault vars in vars file | db_password: "{{ vault_db_password }}" |
| 5 | Encrypt vault file | ansible-vault encrypt vault |
PROHIBITED Secret Practices
| NEVER Do This | ALWAYS Do This Instead |
|---|---|
| Commit plaintext secrets | Use Ansible Vault |
| Hardcode credentials | Use variable references |
| Share vault passwords | Use password files |
| Skip encryption | Encrypt ALL sensitive data |
REQUIRED: Style Rules
Formatting Requirements
| Element | REQUIRED Format | PROHIBITED |
|---|---|---|
| Indentation | 2 spaces | Tabs or 4 spaces |
| Variable names | snake_case | camelCase, kebab-case |
| Quotes | Single quotes | Double quotes (except when nested) |
| Maps | Multi-line ALWAYS | Single-line maps |
| Variables | Alphabetically sorted | Random order |
Play Structure
You MUST order play elements as follows:
| Order | Element |
|---|---|
| 1 | hosts |
| 2 | Host options (alphabetical) |
| 3 | pre_tasks |
| 4 | roles |
| 5 | tasks |
Task Structure
You MUST order task elements as follows:
| Order | Element |
|---|---|
| 1 | name |
| 2 | Module declaration |
| 3 | Module parameters |
| 4 | Loop operators |
| 5 | Task options (alphabetical) |
| 6 | tags |
REQUIRED: State Declaration
You MUST explicitly set state for ALL modules that support it:
# CORRECT - explicit state
- name: Ensure nginx is installed
ansible.builtin.package:
name: nginx
state: present
# PROHIBITED - implicit state
- name: Install nginx
ansible.builtin.package:
name: nginx
REQUIRED: Linting Validation
BEFORE committing, you MUST run:
| Tool | Command | Purpose |
|---|---|---|
| ansible-lint | ansible-lint playbook.yml | Style and best practices |
| yamllint | yamllint playbook.yml | YAML syntax |
| syntax-check | ansible-playbook --syntax-check | Playbook syntax |
| dry-run | ansible-playbook --check --diff | Execution preview |
Validation Checklist
BEFORE deployment, VERIFY:
- All tasks have descriptive names
- FQCN used for all modules
- No shell/command without creates/removes
- Secrets encrypted with Ansible Vault
- ansible-lint passes with no errors
- dry-run completes successfully
Related Assets
Ansible Playbook Creation Assistant
Interactive guide for creating new Ansible playbooks that execute in AWX, following Epic on Azure patterns for role integration, vault secrets, and testing workflows.
Owner: epic-platform-sre
Ansible Playbook Validator
Goal-oriented Ansible specialist that validates playbooks for syntax, idempotency, best practices, and compliance. Autonomously checks collections, roles, and AWX inventory sources. Use for comprehensive playbook validation before deployment.
Owner: platform-automation
Ansible Development Lifecycle for Epic on Azure
Complete development patterns for creating playbooks and roles that execute in AWX, including local development, requirements.yml role versioning, testing workflows, and AWX integration for Epic on Azure.
Owner: epic-platform-sre
AWX Configuration as Code (CaC) Style and Safety
Standard patterns and safety rules for AWX operations using the ansible_role_awx_cac Configuration as Code model in Epic on Azure at Optum.
Owner: epic-platform-sre
Terraform Conventions
Terraform conventions and guardrails for safe, maintainable Infrastructure as Code.
Owner: epic-platform-sre
Terraform Style and Safety for TFE-Backed Workspaces
Terraform coding conventions, safety rules, and best practices for Terraform Enterprise (TFE) backed workspaces in Optum environments.
Owner: epic-platform-sre

