Ansible¶
Folder Hierarchy¶
/ansible
├── inventory/
| ├── group_vars/
| │ │ ├── all/
| | │ ├── vars.yml
| | │ ├── vault.yml
| │ ├── all.yml # Variables that apply to all hosts in the inventory
| │ ├── <group_name_01>.yml # Variables specific to a group of hosts (e.g., webservers, databases)
│ ├── host_vars/
│ │ ├── <server_name_01>/
│ │ │ ├── main.yml
│ │ │ └── vault.yml
│ └── hosts.proxmox.yml
├── playbooks/
│ ├── generated/
│ │ ├── caddy/
│ │ │ └── <caddy_server_01>/
│ │ │ └── example.internal.caddy
│ │ └── <server_name_01>/
│ │ └── docker-compose-<application>.yml
│ ├── samples/
│ ├── site.yml # Main centralized playbook
│ └── system-maintenance.yml # Playbook for general system maintenance tasks
├── roles/
│ └── <role_01>/
│ ├── defaults/ # Default variables for the role, which can be overridden by the user
│ │ └── main.yml
│ ├── handlers/ # Handlers, which are tasks that are triggered by other tasks when certain conditions are met (e.g., restarting a service after a configuration change)
│ │ └── main.yml
│ ├── meta/ # Metadata about the role, such as dependencies on other roles
│ │ └── main.yml
│ ├── tasks/ # The main list of tasks to be executed by the role
│ │ └── main.yml
│ ├── templates/ # Jinja2 templates for configuration files or scripts that will be deployed to the target hosts
│ │ ├── docker-compose.yml.j2
│ │ └── env.j2
│ └── vars/ # Variables that are specific to this role and should not be overridden by the user
│ └── main.yml
└── ansible.cfg
Configuration¶
Rules:
- Configuration of each host in hosts folder
- Keep as few playbooks as possible, and use tags to run specific components when needed
The name site.yml is a convention for the main playbook that orchestrates the execution of other playbooks. It serves as the entry point for running Ansible tasks and typically includes references to other playbooks, roles, or tasks that need to be executed in a specific order.
How to run specific components
[!NOTE] When using OpenBao, it is required to set
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESotherwise it will error with[ERROR]: A worker was found in a dead state
To run only specific components of the Ansible setup without executing the whole thing, we use tags.
Run dns
ansible-playbook -i inventories/production/hosts.yml playbooks/site.yml --tags "dns"
Run the proxy
ansible-playbook -i inventories/production/hosts.yml playbooks/site.yml --tags "proxy"
Run dns and proxy
ansible-playbook -i inventories/production/hosts.yml playbooks/site.yml --tags "dns,proxy"
Run all except dns and proxy
ansible-playbook -i inventories/production/hosts.yml playbooks/site.yml
--skip-tags "dns,proxy"
Generate docker-compose files for one server using --limit (e.g srv_prod_01)
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--limit srv_prod_01 \
--tags generate_manifests
Generate docker-compose files for all servers
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--tags generate_manifests
Update docker images
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--tags apps --skip-tags install_docker
Generate Caddyfiles
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--tags "generate_caddyfile"
Generate DNS files
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--tags "dns"
Ansible tags¶
Notes:
- Prevent tag bleeding: when tags applied to a parent structure are inherited by child tasks
- always is a special, built-in keyword that ensures a task or play runs during every execution, even if other tags are skipped or specific tags are selected via --tags
- Prevent it to run using --skip-tags always
# Usage
tasks:
- name: Always run
tags: [always]
Recommendations 1. Play-level tags - Every task inside the play inherits the tags - Best practice: use play-level for infrastructure categories (proxy, docker, k8s,...)
- The gatekeeper pattern
include_roleimport_role
direct tag
tags: [...]
Allow the loop/input to start if either tag is called
apply
apply force the tag onto every task inside the role. Only use apply for tags that must run for the role to work
apply:
tags: [...]
- Task-level tag
- Give level task a unique task
- Never task for dangerous tasks (e.g database wipes or reboots)
Legacy (Ansible Vault files)¶
Generate docker-compose files for one server using --limit (e.g srv_prod_01)
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--vault-password-file ./playbooks/vault_pass/.srv-prod-01.vault_pass \
--limit srv_prod_01 \
--tags generate_manifests
Generate docker-compose files for all servers
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--vault-password-file ./inventory/group_vars/all/.vault_pass \
--vault-password-file ./playbooks/vault_pass/.srv-prod-01.vault_pass \
--vault-password-file ./playbooks/vault_pass/.security-core.vault_pass \
--vault-password-file ./playbooks/vault_pass/.forgejo-runner.vault_pass \
--vault-password-file ./playbooks/vault_pass/.forgejo.vault_pass \
--tags generate_manifests
Update docker images
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--vault-password-file ./inventory/group_vars/all/.vault_pass \
--vault-password-file ./playbooks/vault_pass/.srv-prod-01.vault_pass \
--vault-password-file ./playbooks/vault_pass/.security-core.vault_pass \
--vault-password-file ./playbooks/vault_pass/.forgejo-runner.vault_pass \
--vault-password-file ./playbooks/vault_pass/.forgejo.vault_pass \
--tags apps --skip-tags install_docker
Generate Caddyfiles
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--vault-password-file ./inventory/group_vars/all/.vault_pass \
--vault-id srv_prod_01@playbooks/vault_pass/.srv-prod-01.vault_pass \
--tags "generate_caddyfile"
Generate DNS files
ansible-playbook -i ./inventory/hosts.proxmox.yml playbooks/site.yml \
--vault-password-file ./inventory/group_vars/all/.vault_pass \
--vault-password-file ./playbooks/vault_pass/.srv-prod-01.vault_pass \
--vault-pass-file inventory/group_vars/all/.vault_pass \
--tags "dns"