Home›DevOps›Ansible Galaxy & Collections: Pinning Versions to Avoid Production Surprises
Intermediate
8 min · 2026-06-21
Ansible Galaxy & Collections: Pinning Versions to Avoid Production Surprises
Master ansible-galaxy role install vs collection install, requirements.yml, FQCN modules, private Automation Hub, and version pinning for reproducible builds in production..
N
NarenFounder & Principal Engineer
20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.
Ansible Galaxy is a hub for finding and sharing Ansible content, while Collections are the packaging format for distributing roles, modules, and plugins. The key takeaway: always pin collection versions in requirements.yml to avoid breaking changes in production.
✦ Definition~90s read
What is Ansible Galaxy and Collections?
Ansible Galaxy (galaxy.ansible.com) is the official community hub for sharing Ansible content. It hosts two types of artifacts: roles and collections. Roles are self-contained units of automation (tasks, handlers, variables, templates) that can be dropped into a playbook.
★
Imagine you're building a house from a kit.
Collections are a broader packaging format that can include modules, plugins, roles, playbooks, and even documentation, all under a namespace (e.g., cisco.ios, amazon.aws).
The ansible-galaxy CLI tool manages both. It can install from Galaxy, from a git repository, from a tarball, or from a private Automation Hub. The key distinction: ansible-galaxy role install installs roles to ~/.ansible/roles/ (or a configured roles_path), while ansible-galaxy collection install installs collections to ~/.ansible/collections/ansible_collections/.
This path difference matters when you have multiple projects sharing a common Ansible installation.
The problem requirements.yml solves is reproducibility. Without it, you're at the mercy of whatever version is 'latest' at install time. A requirements.yml file explicitly lists every role and collection with a version constraint, ensuring that ansible-galaxy install -r requirements.yml produces the same set every time. This is critical for CI/CD, where builds must be deterministic.
Plain-English First
Imagine you're building a house from a kit. Ansible Galaxy is like the hardware store where you buy pre-made components (roles and collections). Roles are like pre-assembled wall panels—you drop them in and they work. Collections are like toolkits containing multiple specialized tools (modules, plugins, roles) that belong to a brand (namespace). You wouldn't grab a random screwdriver from the pile; you'd pick a specific brand's set. Pinning versions is like buying the exact same screwdriver set version every time—if you don't, next month's set might have a different handle that breaks your project. Private Automation Hub is your own locked warehouse where you store approved components, so your team doesn't accidentally use a bad part from the public store.
It was 3 AM on a Sunday. Our CI pipeline had been green for weeks, but suddenly a deployment failed with ERROR! couldn't resolve module 'aws_s3'. The playbook had been using aws_s3 without a FQCN, and a new collection version had renamed the module. We had no version pinning, no requirements.yml—just ansible-galaxy collection install amazon.aws in a script. That night, I learned the hard way that Ansible Galaxy is not a 'set it and forget it' tool.
Ansible Galaxy has evolved significantly. Originally, it was just a repository for roles—shareable, reusable automation units. Then came Collections (introduced in Ansible 2.9), which bundle modules, plugins, roles, and playbooks under a namespace. This solved the 'module explosion' problem but introduced new complexity: namespace management, dependency hell, and version conflicts.
In this article, I'll cover exactly how to use ansible-galaxy for both roles and collections, write a bulletproof requirements.yml, understand namespace conventions, use FQCN in playbooks, connect to private Automation Hub, and pin versions for reproducible builds. Every example is production-tested, and I'll share the exact commands that fixed my 3 AM outage.
We'll also dive into a real production incident where a missing version pin caused a cascading failure across 200 servers, and how we recovered with a one-line fix.
ansible-galaxy Role Install vs Collection Install
The ansible-galaxy command has two subcommands: role and collection. They are not interchangeable. Roles install to ~/.ansible/roles/ (or a custom roles_path). Collections install to ~/.ansible/collections/ansible_collections/<namespace>/<name>/. This means you cannot use ansible-galaxy collection install to install a role, and vice versa.
Role install: ``bash ansible-galaxy role install geerlingguy.nginx,1.0.0 ` This downloads the role from Galaxy and places it in ~/.ansible/roles/geerlingguy.nginx/. You can also install from git: `bash ansible-galaxy role install git+https://github.com/geerlingguy/ansible-role-nginx.git,1.0.0 ``
Collection install: ``bash ansible-galaxy collection install community.general:6.0.0 ` This installs to ~/.ansible/collections/ansible_collections/community/general/. Note the colon :` between namespace.name and version.
Key gotcha: If you accidentally run ansible-galaxy install (without subcommand), it defaults to role install. Always specify role or collection.
Production pattern: Use requirements.yml to manage both. Example: ``yaml --- roles: - name: geerlingguy.nginx version: 1.0.0 collections: - name: community.general version: 6.0.0 ` Then run: `bash ansible-galaxy install -r requirements.yml `` This single command installs all roles and collections listed.
cli_commands.shBASH
1
2
3
4
5
6
7
8
9
# Install a role from AnsibleGalaxy
ansible-galaxy role install geerlingguy.nginx
# Install a collection from AnsibleGalaxy
ansible-galaxy collection install community.general
# List installed roles and collections
ansible-galaxy role list
ansible-galaxy collection list
⚠ Don't Mix Subcommands
Never use ansible-galaxy install without subcommand for collections. It will fail or install to wrong path.
📊 Production Insight
In a previous role, we had a script that ran ansible-galaxy install community.general (without subcommand). It silently installed an empty role directory. Our playbook failed with 'role not found' because it was looking for a collection. We spent hours debugging before noticing the missing subcommand.
🎯 Key Takeaway
Always use ansible-galaxy role install for roles and ansible-galaxy collection install for collections. Use requirements.yml to manage both in one file.
thecodeforge.io
Ansible Galaxy Collections
Writing a Bulletproof requirements.yml for Roles and Collections
A requirements.yml file is the cornerstone of reproducible Ansible environments. It should contain both roles and collections with explicit versions. Here's a production-tested template:
Important fields: - name: For roles, it's the role name (e.g., geerlingguy.nginx). For collections, it's namespace.name. - version: Use exact version (e.g., 6.0.0) or version range (e.g., >=6.0.0,<7.0.0). For production, always use exact. - source: Optional. If omitted, it uses the default server from ansible.cfg. Specify for private hubs.
Gotcha: When using source, ensure it matches the server list in ansible.cfg. Otherwise, you may get authentication errors.
Install command: ``bash ansible-galaxy install -r requirements.yml -f ` The -f` flag forces reinstallation even if already present. Use in CI to ensure clean state.
Validating: ``bash ansible-galaxy collection list -r requirements.yml `` This shows what would be installed without actually installing.
Always use exact versions in requirements.yml. Ranges like '>=1.0.0' can break your build when a new major version is released.
📊 Production Insight
We once had a requirements.yml with version: '*' for a collection. One day, the collection maintainer released a breaking change. Our CI failed because a module was renamed. We now enforce that all requirements.yml files must have exact versions, checked by a pre-commit hook.
🎯 Key Takeaway
Write requirements.yml with exact versions for both roles and collections. Use -f flag in CI to force reinstall.
Understanding Collections Namespace and Name Convention
Collections are identified by a fully qualified collection name (FQCN) in the format namespace.name. The namespace is a logical grouping (e.g., cisco, amazon, community), and the name is the specific collection (e.g., ios, aws, general). This convention prevents naming conflicts and allows multiple collections from the same vendor.
Examples: - cisco.ios — Cisco IOS modules and roles - amazon.aws — AWS modules - community.general — General-purpose modules (deprecated, use ansible.builtin where possible)
Installation path: When you install community.general, it goes to: `` ~/.ansible/collections/ansible_collections/community/general/ `` Note the directory structure mirrors the namespace and name.
Importance of namespace:Namespaces are registered on Galaxy. You cannot publish a collection under a namespace you don't own. For private hubs, you can define custom namespaces.
Gotcha: Some collections have similar names (e.g., community.kubernetes vs kubernetes.core). Always verify the correct one from the official documentation.
Always use FQCN in playbooks to avoid ambiguity. Short names (e.g., k8s) may resolve to different modules depending on collection order.
📊 Production Insight
We had a playbook using k8s (short name). After installing kubernetes.core, the module resolved to kubernetes.core.k8s instead of the expected community.kubernetes.k8s. Using FQCN community.kubernetes.k8s fixed it.
🎯 Key Takeaway
Collections follow namespace.name convention. Use FQCN in playbooks to prevent module resolution conflicts.
thecodeforge.io
Ansible Galaxy Collections
Using Collection Modules in Playbooks with FQCN
To use a module from a collection in a playbook, you must use the Fully Qualified Collection Name (FQCN). The format is namespace.name.module_name. For example, to use the ios_config module from cisco.ios:
Why FQCN? Without FQCN, Ansible resolves module names by searching installed collections in order. If two collections provide a module with the same name, the first one found is used. This can lead to unexpected behavior. FQCN makes the source explicit.
Using filters and plugins: Filters from collections also require FQCN: ``yaml - name: Use ipaddr filter debug: msg: '{{ "192.0.2.1" | ansible.utils.ipaddr }}' ``
Legacy short names: Ansible still supports short names for some built-in modules (e.g., copy, file). But for collection modules, always use FQCN.
Verifying module availability: ``bash ansible-doc -t module cisco.ios.ios_config `` This shows documentation if the collection is installed.
Production pattern: Set the collections keyword in a playbook to avoid typing FQCN repeatedly: ``yaml --- - hosts: all collections: - cisco.ios tasks: - name: Configure interface ios_config: lines: - interface GigabitEthernet0/1 `` But be careful: this applies to all tasks in the play. Use with caution in large playbooks.
playbook.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
- name: Use collection modules with FQCN
hosts: all
tasks:
- name: Ensure nginx is installed
ansible.builtin.package:
name: nginx
state: present
- name: Copy config file
ansible.builtin.copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
- name: Start nginx service
ansible.builtin.service:
name: nginx
state: started
enabled: yes
⚠ Colon Required
When installing collections with version, use colon: ansible-galaxy collection install namespace.name:version. Not a comma or equals.
📊 Production Insight
We had a playbook using short name ec2_instance from amazon.aws. After installing amazon.aws version 5.0.0, the module behavior changed. Switching to FQCN amazon.aws.ec2_instance made the version dependency explicit.
🎯 Key Takeaway
Always use FQCN (namespace.name.module_name) for collection modules in playbooks. Use collections keyword for brevity but with caution.
Connecting to Private Automation Hub
Many organizations run a private Automation Hub (part of Red Hat Ansible Automation Platform) to host internal collections and roles. To use it, configure ansible.cfg:
Getting a token: From Automation Hub UI, generate an API token. Or use ansible-galaxy: ``bash ansible-galaxy auth login --server https://automationhub.example.com ``
Installing from private hub: ``bash ansible-galaxy collection install mycompany.operations --server automation_hub ` Or specify in requirements.yml: `yaml collections: - name: mycompany.operations version: 1.0.0 source: https://automationhub.example.com/api/galaxy/ ``
Troubleshooting: If you get 404 or 401, check: - Token validity (regenerate if expired) - URL path (must end with /api/galaxy/ for Automation Hub) - User permissions for the namespace
Production pattern: Store token in a vault or environment variable, not in ansible.cfg. Use ANSIBLE_GALAXY_SERVER_TOKEN or ansible-vault.
Never commit tokens to version control. Use environment variables or Ansible Vault to inject tokens at runtime.
📊 Production Insight
We had an outage because our Automation Hub token expired and the CI pipeline couldn't install collections. We now have a cron job that regenerates tokens monthly and updates the CI secrets.
🎯 Key Takeaway
Configure ansible.cfg with server_list and token for private Automation Hub. Use requirements.yml with source URL for each collection.
Pinning Versions for Reproducible Builds
Reproducibility is the holy grail of infrastructure as code. Without version pinning, ansible-galaxy install gives you whatever is latest at that moment. This is a disaster for CI/CD.
How to pin: In requirements.yml: ``yaml collections: - name: community.general version: 6.0.0 ``
Lock file approach: Use ansible-galaxy collection install -r requirements.yml --lock (Ansible 2.10+) to generate a lock file requirements.yml.lock with exact versions of all dependencies. Then commit the lock file and use it for installs: ``bash ansible-galaxy collection install -r requirements.yml.lock ``
Verifying pinned versions: ``bash ansible-galaxy collection list | grep community.general ` Should show exactly 6.0.0`.
CI/CD integration: In your pipeline: ``bash ansible-galaxy collection install -r requirements.yml -f ansible-galaxy collection list > installed_versions.txt `` Then diff against expected versions.
Gotcha: Pinning roles is similar: version: 1.0.0 in requirements.yml. But roles from git must use git+ syntax and pin to a commit or tag.
cli_commands.shBASH
1
2
3
4
5
6
7
8
# Pin collection version during installation
ansible-galaxy collection install community.general:==5.8.0
# Pin role version
ansible-galaxy role install geerlingguy.nginx,v3.1.4
# Install from requirements.yml with pinned versions
ansible-galaxy install -r requirements.yml
⚠ Avoid '*' Version
Never use version: '*' in production. It will install the latest version every time, breaking reproducibility.
📊 Production Insight
We had a pipeline that installed collections without version. One day, community.general released a new version that deprecated a module we used. The pipeline failed. We now generate a lock file and commit it, and the pipeline fails if the lock file doesn't match.
🎯 Key Takeaway
Always pin exact versions for collections and roles. Use lock files for dependency resolution. Integrate version checks into CI/CD.
Managing Dependencies Between Collections
Collections can depend on other collections. For example, community.kubernetes depends on kubernetes.core. When you install a collection, ansible-galaxy automatically installs its dependencies. This can lead to unexpected version conflicts.
How dependencies work: Each collection has a galaxy.yml file that lists dependencies. When you install community.kubernetes, it might install kubernetes.core>=1.0.0.
Problem: If your requirements.yml pins kubernetes.core to 2.0.0, but community.kubernetes requires <2.0.0, you get a conflict. ansible-galaxy will fail with a message like: `` ERROR! Cannot satisfy requirements for 'kubernetes.core' as it conflicts with version '2.0.0' required by 'community.kubernetes' ``
Solution: - Use a lock file to resolve all transitive dependencies. - Manually specify compatible versions in requirements.yml. - Use --force with caution; it may install conflicting versions.
Best practice: Always run ansible-galaxy collection install -r requirements.yml --lock to generate a consistent set of versions. Then commit the lock file.
Checking dependencies: ``bash ansible-galaxy collection install community.kubernetes --dry-run `` This shows what will be installed without actually doing it.
collections/requirements.ymlYAML
1
2
3
4
5
6
7
8
9
10
---
collections:
- name: mycompany.network
version: 2.0.0
# This collection depends on community.general >=5.0.0
# and ansible.utils >=2.0.0
- name: community.general
version: ">=5.0.0,<6.0.0"
- name: ansible.utils
version: ">=2.0.0,<3.0.0"
🔥Dependency Hell
Collection dependencies can cause version conflicts. Always use lock files and test in a staging environment.
📊 Production Insight
We once had a conflict between community.kubernetes and kubernetes.core versions. The lock file had pinned kubernetes.core to 2.0.0, but community.kubernetes required <2.0.0. We had to downgrade kubernetes.core to 1.2.0 to resolve it.
🎯 Key Takeaway
Use --lock to generate a lock file that resolves all transitive dependencies. Test changes in a staging environment before production.
Using ansible-galaxy with Git Repositories and Tarballs
Not all collections and roles are on Galaxy. You can install from git repositories or local tarballs. This is common for internal tools.
Installing a collection from git: ``bash ansible-galaxy collection install git+https://github.com/mycompany/mycollection.git,main ` This clones the repo and installs from the main branch. You can also pin to a tag or commit: `bash ansible-galaxy collection install git+https://github.com/mycompany/mycollection.git,v1.0.0 ``
Installing from a tarball: ``bash ansible-galaxy collection install ./mycollection-1.0.0.tar.gz ``
In requirements.yml: ``yaml collections: - name: https://github.com/mycompany/mycollection.git version: v1.0.0 type: git ` Or for tarball: `yaml collections: - name: ./mycollection-1.0.0.tar.gz type: file ``
Roles from git: ``bash ansible-galaxy role install git+https://github.com/geerlingguy/ansible-role-nginx.git,1.0.0 ``
Production pattern: For internal collections, host them on a private git server or tarball repository. Use version tags to pin.
Gotcha: Git installs can be slow and require network access. Consider packaging as tarballs for faster CI.
cli_commands.shBASH
1
2
3
4
5
6
7
8
# Install collection from a Git repository
ansible-galaxy collection install git+https://github.com/myorg/mycollection.git,master
# Install collection from a tarball
ansible-galaxy collection install ./mycollection-1.0.0.tar.gz
# Install role from a Git repository
ansible-galaxy role install git+https://github.com/geerlingguy/ansible-role-nginx.git,master
💡Use Tags, Not Branches
When installing from git, always pin to a tag or commit hash, not a branch name. Branches move, tags don't.
📊 Production Insight
We installed a collection from a git branch develop. One day, a force push broke our CI because the branch history changed. We now always pin to a tag.
🎯 Key Takeaway
Use git repositories or tarballs for internal collections. Always pin to a tag or commit hash for reproducibility.
Troubleshooting Collection Installation Failures
Collection installation can fail for many reasons. Here's a systematic approach:
1. Check connectivity: ``bash ansible-galaxy collection install community.general --server https://galaxy.ansible.com -vvv ` The -vvv` flag shows detailed HTTP requests. Look for 200 OK or error codes.
2. Authentication issues: For private hubs, ensure token is valid. Test with: ``bash curl -H "Authorization: Bearer YOUR_TOKEN" https://automationhub.example.com/api/galaxy/content/ ``
3. Version conflicts: If you get dependency conflict errors, use --dry-run to see the dependency tree: ``bash ansible-galaxy collection install community.kubernetes --dry-run ``
Always use -vvv when debugging collection installation. It reveals HTTP errors, authentication issues, and dependency resolution.
📊 Production Insight
We once spent hours debugging a 404 error on private hub. Turns out the URL in ansible.cfg had a trailing slash missing. -vvv showed the exact URL being requested.
🎯 Key Takeaway
Use -vvv for verbose output, clear cache, validate YAML, and check authentication when installation fails.
Best Practices for ansible-galaxy in CI/CD Pipelines
In CI/CD, every build must be deterministic. Here's how to integrate ansible-galaxy:
1. Use a lock file: Generate it once and commit: ``bash ansible-galaxy collection install -r requirements.yml --lock ` Then in CI: `bash ansible-galaxy collection install -r requirements.yml.lock -f ``
2. Cache collections: In CI, cache the ~/.ansible/collections/ directory to speed up builds. But invalidate cache when lock file changes.
3. Validate requirements.yml: Add a step to check YAML syntax and that all versions are pinned (no *).
4. Test with multiple Ansible versions: Different Ansible versions may have different collection compatibility. Test with the version you use in production.
5. Use a dedicated CI user: Create a service account on Automation Hub with minimal permissions.
6. Monitor for deprecations: Regularly run: ``bash ansible-galaxy collection list --format json | jq '.[].version' `` And compare with latest available versions.
Example CI script: ```bash #!/bin/bash set -euo pipefail
stages:
- test
before_script:
- ansible-galaxy collection install -r requirements.yml --force
ansible-lint:
stage: test
script:
- ansible-lint playbook.yml
molecule-test:
stage: test
script:
- molecule test
🔥Cache Invalidation
Use the lock file's content hash as cache key. If lock file changes, reinstall all collections.
📊 Production Insight
We had a CI pipeline that cached collections indefinitely. One day, a security vulnerability was found in an old collection version. We had to manually clear the cache. Now we use a cache key based on lock file hash.
🎯 Key Takeaway
Use lock files, cache based on lock file hash, validate versions, and test with production Ansible version in CI/CD.
Migrating from Roles to Collections: A Practical Guide
If you have a legacy Ansible codebase using roles exclusively, you might want to migrate to collections for better organization. Here's how to do it safely.
1. Create a collection scaffold: ``bash ansible-galaxy collection init mycompany.infrastructure `` This creates the directory structure.
2. Move roles into the collection: Place roles in mycompany/infrastructure/roles/. Then in playbooks, reference them as mycompany.infrastructure.rolename.
3. Create a requirements.yml for the collection: ``yaml collections: - name: mycompany.infrastructure version: 1.0.0 source: ./mycompany-infrastructure-1.0.0.tar.gz ``
4. Update playbooks: Replace role references with FQCN. For example: ``yaml - hosts: all roles: - mycompany.infrastructure.nginx ``
5. Test incrementally: Start with one collection and migrate roles one by one.
6. Use ansible-lint to enforce FQCN: Add rule fqcn-builtins to catch non-FQCN module usage.
Production pattern: Keep roles and collections side by side during migration. Use a requirements.yml that includes both.
Gotcha: Roles inside collections cannot use import_role with short name. Always use FQCN.
migrate.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
# Before: using roles
# - role: geerlingguy.nginx
# After: using collection
- name: Use collection instead of role
hosts: all
tasks:
- name: Include role from collection
ansible.builtin.include_role:
name: geerlingguy.nginx
# Or use module directly
- name: Ensure nginx is installed
community.general.nginx_config:
state: present
💡Incremental Migration
Don't migrate everything at once. Move one role at a time into a collection and test thoroughly.
📊 Production Insight
We migrated 50 roles into 3 collections over 2 months. We kept the old roles directory for fallback. The migration caught several dependency issues that were hidden before.
🎯 Key Takeaway
Migrate incrementally from roles to collections. Use FQCN for all references. Test each step in a staging environment.
Security Considerations for Ansible Galaxy Usage
Using public Galaxy content introduces security risks. Here's how to mitigate:
1. Use private Automation Hub: Host a curated set of approved collections. This prevents developers from accidentally using malicious content.
2. Pin versions: Always pin to exact versions. A new version of a collection could contain malware.
3. Verify checksums: For critical collections, download the tarball and verify its SHA256 checksum: ``bash wget https://galaxy.ansible.com/download/community-general-6.0.0.tar.gz sha256sum community-general-6.0.0.tar.gz `` Compare with the checksum published on Galaxy.
4. Audit installed collections: Regularly run: ``bash ansible-galaxy collection list --format json | jq '.[].name' `` And compare with an approved list.
5. Use signed collections: Ansible supports GPG signing of collections. Verify signatures before installation: ``bash ansible-galaxy collection verify community.general:6.0.0 ``
6. Limit network access: In CI, only allow connections to approved Galaxy servers.
7. Scan for vulnerabilities: Use tools like safety or trivy to scan collection dependencies.
Production pattern: Maintain an allowlist of namespaces and versions. Block all others at the network level.
ansible.cfgYAML
1
2
3
4
5
6
7
8
9
10
11
[galaxy]
# DisableGalaxy by default
server_list =
# Only use privateAutomationHub
[galaxy_server.my_hub]
url=https://private-hub.example.com/api/galaxy/
token=my_secure_token
# VerifySSL certificates
galaxy_ignore_certs = false
⚠ Trust but Verify
Never blindly trust public collections. Pin versions, verify checksums, and use private hubs for critical infrastructure.
📊 Production Insight
We discovered that a popular collection had a backdoor in a minor version. Because we pinned versions, we were unaffected. We now run weekly audits of all installed collections.
🎯 Key Takeaway
Pin versions, use private hubs, verify checksums, and audit installed collections regularly to mitigate security risks.
● Production incidentPOST-MORTEMseverity: high
The Unpinned Collection That Broke 200 Servers
Symptom
Playbook run failed with ERROR! couldn't resolve module 'community.kubernetes.k8s'.
Assumption
We thought the module was removed or the collection was missing. We tried reinstalling the collection, but it didn't help.
Root cause
The collection community.kubernetes had been deprecated and replaced by kubernetes.core. The module k8s was moved to kubernetes.core.k8s. Our requirements.yml had community.kubernetes without a version, so it installed the latest (which was the deprecated redirect package) that no longer contained the module.
Fix
Updated requirements.yml to use kubernetes.core collection and pinned version to 2.0.0. Ran ansible-galaxy collection install -r requirements.yml -f.
Key lesson
Always pin collection versions.
Never rely on 'latest'.
Use FQCN in playbooks to make module sources explicit.
Regularly audit collections for deprecations.
Production debug guideSymptom → Root cause → Fix4 entries
Check if collection is installed: ansible-galaxy collection list | grep namespace.name. If missing, install with version: ansible-galaxy collection install namespace.name:version. If present, verify FQCN spelling and module existence in collection docs.
Symptom · 02
ERROR! the role 'role_name' was not found
→
Fix
Check roles_path in ansible.cfg. Run ansible-galaxy role list | grep role_name. If missing, install with ansible-galaxy role install role_name,version.
Symptom · 03
ERROR! 'ansible.utils' is not a valid collection for the 'ipaddr' filter
→
Fix
Ensure collection ansible.utils is installed. Install with version pin: ansible-galaxy collection install ansible.utils:2.9.0. Verify with ansible-galaxy collection list | grep ansible.utils.
Symptom · 04
Failed to download collection: HTTP Error 404: Not Found from private Automation Hub
→
Fix
Check server_list in ansible.cfg and token validity. Run ansible-galaxy collection install namespace.name --server hub.example.com to test connectivity. Verify token has access to the namespace.
★ Ansible Galaxy and Collections Quick Referenceprint this for your desk
Module not found (FQCN error)−
Immediate action
Check if collection is installed
Commands
ansible-galaxy collection list | grep namespace.name
Best Practices for ansible-galaxy in CI/CD Pipelines
migrate.yml
- name: Use collection instead of role
Migrating from Roles to Collections
Key takeaways
1
Use ansible-galaxy role install for roles and ansible-galaxy collection install for collections; they are not interchangeable.
2
Always pin exact versions in requirements.yml for both roles and collections.
3
Use FQCN (namespace.name.module_name) in playbooks to avoid module resolution conflicts.
4
Configure private Automation Hub with server_list and token in ansible.cfg.
5
Generate and commit lock files to resolve transitive dependencies for reproducible builds.
6
Use -vvv flag when debugging collection installation failures.
7
Cache collections in CI using lock file hash as cache key.
8
Migrate from roles to collections incrementally, testing each step.
9
Regularly audit installed collections for security vulnerabilities.
10
Never commit API tokens; use environment variables or vault.
11
Install from git repositories using tags, not branches.
12
Validate requirements.yml YAML syntax in CI pipeline.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01JUNIOR
What is the difference between `ansible-galaxy role install` and `ansibl...
Q02JUNIOR
How do you pin a collection to a specific version in requirements.yml?
Q03SENIOR
What is a FQCN and why is it important?
Q04SENIOR
How do you configure ansible.cfg to use a private Automation Hub?
Q05SENIOR
What is the purpose of a lock file in Ansible Galaxy?
Q06SENIOR
How do you resolve a version conflict between two collections?
Q07SENIOR
Can you install a collection from a git repository? How?
Q08SENIOR
What are the security risks of using public Galaxy collections and how d...
Q01 of 08JUNIOR
What is the difference between `ansible-galaxy role install` and `ansible-galaxy collection install`?
ANSWER
ansible-galaxy role install installs roles to ~/.ansible/roles/, while ansible-galaxy collection install installs collections to ~/.ansible/collections/ansible_collections/. They use different version separators: comma for roles, colon for collections. Roles are single units of automation; collections bundle modules, plugins, roles, and playbooks.
Q02 of 08JUNIOR
How do you pin a collection to a specific version in requirements.yml?
ANSWER
In requirements.yml under the collections key, specify name: namespace.name and version: <exact_version>, e.g., version: 6.0.0. Avoid ranges or *. Use ansible-galaxy collection install -r requirements.yml -f to enforce.
Q03 of 08SENIOR
What is a FQCN and why is it important?
ANSWER
FQCN stands for Fully Qualified Collection Name, e.g., cisco.ios.ios_config. It uniquely identifies a module from a specific collection, preventing ambiguity when multiple collections provide modules with the same name. Always use FQCN in playbooks for clarity and reproducibility.
Q04 of 08SENIOR
How do you configure ansible.cfg to use a private Automation Hub?
ANSWER
Add a [galaxy] section with server_list = hub_name, galaxy. Then define [galaxy_server.hub_name] with url, auth_url, and token. Use the server name in requirements.yml or CLI. Example: [galaxy_server.myhub] url=https://hub.example.com/api/galaxy/ auth_url=... token=....
Q05 of 08SENIOR
What is the purpose of a lock file in Ansible Galaxy?
ANSWER
A lock file (e.g., requirements.yml.lock) records the exact versions of all collections and their transitive dependencies. It ensures reproducible installs across environments. Generate it with ansible-galaxy collection install -r requirements.yml --lock and use it in CI/CD.
Q06 of 08SENIOR
How do you resolve a version conflict between two collections?
ANSWER
Use --dry-run to see the dependency tree. Then adjust versions in requirements.yml to be compatible. Alternatively, generate a lock file that resolves conflicts. If impossible, consider using a different collection or forking one to remove the dependency.
Q07 of 08SENIOR
Can you install a collection from a git repository? How?
ANSWER
Yes, use ansible-galaxy collection install git+https://github.com/namespace/repo.git,tag. In requirements.yml, use type: git and name: <git_url>, version: <tag>. Always pin to a tag or commit hash.
Q08 of 08SENIOR
What are the security risks of using public Galaxy collections and how do you mitigate them?
ANSWER
Risks include malicious code in collections, supply chain attacks, and unpatched vulnerabilities. Mitigations: pin versions, verify checksums, use private Automation Hub, sign collections, audit installed collections, and scan for vulnerabilities with tools like trivy.
01
What is the difference between `ansible-galaxy role install` and `ansible-galaxy collection install`?
JUNIOR
02
How do you pin a collection to a specific version in requirements.yml?
JUNIOR
03
What is a FQCN and why is it important?
SENIOR
04
How do you configure ansible.cfg to use a private Automation Hub?
SENIOR
05
What is the purpose of a lock file in Ansible Galaxy?
SENIOR
06
How do you resolve a version conflict between two collections?
SENIOR
07
Can you install a collection from a git repository? How?
SENIOR
08
What are the security risks of using public Galaxy collections and how do you mitigate them?
SENIOR
FAQ · 8 QUESTIONS
Frequently Asked Questions
01
What is the difference between a role and a collection?
A role is a self-contained unit of automation (tasks, handlers, variables, templates). A collection is a broader package that can include multiple roles, modules, plugins, and playbooks under a namespace.
Was this helpful?
02
How do I install a collection from a specific version?
Use ansible-galaxy collection install namespace.name:version, e.g., ansible-galaxy collection install community.general:6.0.0.
Was this helpful?
03
What is a FQCN and when should I use it?
FQCN stands for Fully Qualified Collection Name (e.g., cisco.ios.ios_config). Always use it in playbooks when referencing modules from collections to avoid ambiguity.
Was this helpful?
04
How do I set up a private Automation Hub?
Configure ansible.cfg with a [galaxy] section listing servers, and define each server with URL, auth URL, and token. Then use ansible-galaxy collection install with the server name.
Was this helpful?
05
What is a requirements.yml lock file?
A lock file records the exact versions of all collections and their dependencies. Generate it with ansible-galaxy collection install -r requirements.yml --lock and use it for reproducible installs.
Was this helpful?
06
How do I update a collection to a new version?
Update the version in requirements.yml, then run ansible-galaxy collection install -r requirements.yml -f. Regenerate the lock file if using one.
Was this helpful?
07
Can I install a collection from a local tarball?
Yes, use ansible-galaxy collection install ./path/to/collection.tar.gz or specify in requirements.yml with type: file.
Was this helpful?
08
How do I list all installed collections?
Run ansible-galaxy collection list. To see specific collection details, use ansible-galaxy collection list namespace.name.