Ansible Plugins: Types, Usage & Custom Plugin Development Guide
By Luca Berton · Published 2024-01-01 · Category: installation
Complete guide to Ansible plugins. Understand lookup, callback, filter, connection, inventory, and module plugins with usage examples and custom development.
Ansible plugins are modular pieces of code that extend and enhance Ansible’s core functionality. They allow users to customize and optimize workflows for specific requirements. This article explains what Ansible plugins are, their types, and how to use them effectively.
What Are Ansible Plugins?
Ansible plugins are Python-based extensions that modify or add capabilities to Ansible’s automation engine. They provide additional functionality without altering the core Ansible codebase, making them highly flexible and reusable.
Key Features:
• Extensibility: Add new behaviors to Ansible. • Reusability: Share plugins across projects or teams. • Customization: Tailor functionality to specific needs.See also: Ansible Development: Write Custom Modules, Plugins & Collections
Types of Ansible Plugins
Ansible supports several plugin types, each serving a distinct purpose:
1. Action Plugins
Modify or enhance the behavior of modules when executed. • Example: Add custom logic to module execution.2. Lookup Plugins
Fetch data from external sources and pass it into playbooks. • Example: Retrieve secrets from a vault: vars:
secret: "{{ lookup('aws_secretsmanager', 'my_secret') }}"
3. Filter Plugins
Transform data or variables in templates or playbooks. • Example: Convert text to uppercase: vars:
uppercase_text: "{{ 'hello' | upper }}"
4. Connection Plugins
Define how Ansible connects to target nodes (e.g., SSH, WinRM). • Example: Use a custom connection method for specialized devices.5. Strategy Plugins
Control the execution flow of tasks in a play. • Built-in strategies includelinear, free, and debug.
6. Callback Plugins
Customize output or perform actions during playbook execution. • Example: Send notifications to Slack after task completion.7. Inventory Plugins
Dynamically generate inventory from external sources (e.g., AWS, GCP). • Example: plugin: aws_ec2
regions:
- us-east-1
8. Vars Plugins
Inject additional variables into playbooks dynamically. • Example: Load variables based on host properties.Where Are Plugins Stored?
Built-In Plugins
Ansible’s default plugins are stored in the system directory:/usr/share/ansible/plugins/
Custom Plugins
Custom plugins can be stored in: Project-Specific Directory: ./plugins/<plugin_type>/
Global Directory:
~/.ansible/plugins/<plugin_type>/
Specified Paths:
Define custom plugin paths in the ansible.cfg file:
[defaults]
plugin_paths = /path/to/custom/plugins
See also: Ansible vs Terraform: Key Differences & When to Use Each (2026 Guide)
Creating Custom Plugins
Here’s an example of a custom filter plugin to reverse strings: Create a directory for custom plugins:
./plugins/filter/
Write the plugin in Python:
# plugins/filter/reverse.py
def reverse_string(value):
return value[::-1]
class FilterModule(object):
def filters(self):
return {
'reverse': reverse_string
}
Use the plugin in a playbook:
vars:
reversed_text: "{{ 'hello' | reverse }}"
Execute the playbook to see the plugin in action.
Best Practices for Using Plugins
Use Collections: Distribute and manage plugins using Ansible Collections for better organization. Test Custom Plugins: Validate plugins in a controlled environment to ensure reliability. Document Plugins: Provide clear documentation for custom plugins, including usage examples. Optimize for Performance: Ensure plugins do not introduce significant overhead to playbook execution.See also: Ansible vs Terraform: Are They the Same? Key Differences Explained (2026)
Conclusion
Ansible plugins are a powerful way to extend Ansible’s functionality and customize workflows to meet unique requirements. With various built-in types and support for custom development, plugins empower users to optimize their automation tasks effectively.
Learn More About Ansible Plugins
Plugin Types
| Type | Purpose | Example |
|------|---------|---------|
| Connection | How Ansible connects to hosts | ssh, winrm, local, docker |
| Callback | Output formatting and events | default, json, yaml, unixy |
| Lookup | Retrieve data from external sources | file, env, password, template |
| Filter | Transform data in Jinja2 | to_json, regex_search, combine |
| Inventory | Dynamic inventory sources | aws_ec2, azure_rm, vmware_vm_inventory |
| Strategy | Execution strategy | linear, free, debug |
| Vars | Load variables from sources | host_group_vars |
| Cache | Cache facts between runs | jsonfile, redis, memcached |
| Test | Jinja2 test functions | defined, match, search |
| Module | Task execution units | copy, apt, user |
Connection Plugins
# SSH (default)
ansible_connection: ssh
# Local (no SSH)
ansible_connection: local
# Docker
ansible_connection: community.docker.docker
# WinRM
ansible_connection: winrm
Callback Plugins
# ansible.cfg
[defaults]
stdout_callback = yaml # YAML formatted output
callbacks_enabled = timer, profile_tasks
# One-time override
ANSIBLE_STDOUT_CALLBACK=json ansible-playbook site.yml
Lookup Plugins
- debug:
msg:
- "File: {{ lookup('file', '/etc/hostname') }}"
- "Env: {{ lookup('env', 'HOME') }}"
- "Password: {{ lookup('password', '/tmp/pw length=16') }}"
- "Template: {{ lookup('template', 'msg.j2') }}"
- "URL: {{ lookup('url', 'https://api.example.com/status') }}"
- "Pipe: {{ lookup('pipe', 'date +%Y-%m-%d') }}"
Filter Plugins
- debug:
msg:
- "{{ my_list | sort | unique }}"
- "{{ my_dict | to_nice_json }}"
- "{{ 'hello' | upper }}"
- "{{ password | password_hash('sha512') }}"
Inventory Plugins
# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
keyed_groups:
- key: tags.Environment
prefix: env
Strategy Plugins
# Default: linear (task by task)
- hosts: all
strategy: free # Each host runs independently
# Debug strategy (interactive)
- hosts: all
strategy: debug # Pause on errors for debugging
Custom Plugin Locations
my-project/
lookup_plugins/ # Custom lookup plugins
filter_plugins/ # Custom filter plugins
callback_plugins/ # Custom callback plugins
connection_plugins/ # Custom connection plugins
inventory_plugins/ # Custom inventory plugins
Write a Custom Filter Plugin
# filter_plugins/my_filters.py
class FilterModule:
def filters(self):
return {
'double': lambda x: x * 2,
'prefix': lambda x, p: f"{p}_{x}",
}
- debug:
msg: "{{ 5 | double }}" # 10
List Available Plugins
ansible-doc -t callback -l # List callback plugins
ansible-doc -t lookup -l # List lookup plugins
ansible-doc -t connection -l # List connection plugins
ansible-doc -t inventory -l # List inventory plugins
FAQ
Plugins vs Modules?
Modules are a type of plugin that execute tasks. Other plugins extend Ansible's core functionality (connections, output, data retrieval).
Where are plugins installed?
Built-in: with Ansible installation. Collection plugins: ~/.ansible/collections/. Custom: in project *_plugins/ directories.
Can I use plugins from collections?
Yes — most collections include plugins. Use FQCN: community.general.json_query (filter), amazon.aws.aws_ec2 (inventory).
Plugin Types
| Type | Purpose | Example |
|------|---------|---------|
| Lookup | Retrieve data | file, env, password |
| Filter | Transform data | to_json, regex_replace |
| Callback | Control output | json, yaml, timer |
| Connection | Connect to hosts | ssh, winrm, docker |
| Inventory | Dynamic inventory | aws_ec2, azure_rm |
| Module | Execute tasks | copy, apt, file |
| Strategy | Execution strategy | linear, free, debug |
| Vars | Load variables | host_group_vars |
| Cache | Cache facts | jsonfile, redis |
| Test | Jinja2 tests | match, search |
Lookup Plugins
# File
msg: "{{ lookup('file', '/etc/hostname') }}"
# Environment variable
msg: "{{ lookup('env', 'HOME') }}"
# Password generation
msg: "{{ lookup('password', '/dev/null length=16') }}"
# Template
msg: "{{ lookup('template', 'my.conf.j2') }}"
# Pipe (run command)
msg: "{{ lookup('pipe', 'date +%Y%m%d') }}"
# URL
msg: "{{ lookup('url', 'https://api.example.com/version') }}"
# Vault-encrypted file
msg: "{{ lookup('file', 'secrets/api_key.vault') }}"
Filter Plugins
# Built-in
"{{ name | upper }}"
"{{ list | join(', ') }}"
"{{ dict | to_nice_json }}"
"{{ hash | combine(overrides) }}"
"{{ 'text' | regex_replace('old', 'new') }}"
"{{ path | basename }}"
"{{ timestamp | to_datetime }}"
# Ansible-specific
"{{ pass | password_hash('sha512') }}"
"{{ groups['web'] | map('extract', hostvars, 'ansible_host') | list }}"
"{{ my_var | type_debug }}"
Callback Plugins
# ansible.cfg
[defaults]
# Change output format
stdout_callback = yaml
# Enable additional callbacks
callbacks_enabled = timer, profile_tasks
# List available callbacks
ansible-doc -t callback -l
Connection Plugins
# SSH (default for Linux)
[linux]
server1 ansible_connection=ssh
# WinRM (Windows)
[windows]
win1 ansible_connection=winrm
# Docker container
[containers]
myapp ansible_connection=community.docker.docker
# Local (run on controller)
[local]
localhost ansible_connection=local
Custom Filter Plugin
# plugins/filter/custom_filters.py
class FilterModule:
def filters(self):
return {
'reverse_dns': self.reverse_dns,
'to_cidr': self.to_cidr,
}
def reverse_dns(self, ip):
parts = ip.split('.')
return '.'.join(reversed(parts)) + '.in-addr.arpa'
def to_cidr(self, ip, prefix=24):
return f"{ip}/{prefix}"
# Usage
msg: "{{ '10.0.1.5' | reverse_dns }}"
# "5.1.0.10.in-addr.arpa"
Custom Lookup Plugin
# plugins/lookup/my_lookup.py
from ansible.plugins.lookup import LookupBase
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
results = []
for term in terms:
results.append(term.upper())
return results
Plugin Search Path
# ansible.cfg
[defaults]
lookup_plugins = ./plugins/lookup
filter_plugins = ./plugins/filter
callback_plugins = ./plugins/callback
FAQ
How to list all available plugins?
ansible-doc -t lookup -l # Lookups
ansible-doc -t callback -l # Callbacks
ansible-doc -t inventory -l # Inventory
Where are built-in plugins stored?
In the Ansible Python package: ansible/plugins/. Collection plugins are in ~/.ansible/collections/.
Can I override built-in plugins?
Yes — place a plugin with the same name in your local plugin directory. Local plugins take precedence.
Related Articles
• secrets management with Ansible Vault • Ansible template vs copy module • Ansible Inventory Guide • IAM management via Ansible on AWSCategory: installation