A production controller that runs ansible-galaxy collection install
against public Galaxy as part of a deployment has put a third-party
website in the critical path of every change it makes.
That is three problems in one sentence:
Availability. Galaxy is down, or slow, or rate-limiting your CI
runners, and your change window closes with nothing deployed.
Integrity. Whatever the endpoint serves today is what runs as
root on your fleet today. Lesson 6’s verification only helps if you
have something to compare against, and a fresh fetch is not it.
Reproducibility. The install is not the same install twice, for
all the reasons lesson 4 laid out.
The fix is not exotic. Fetch deliberately, once, into an artefact you
keep — then install from the artefact.
The offline bundle
ansible-galaxy collection download resolves the dependency tree and
writes tarballs instead of installing them:
Configuration changefetch the tree, install nothing— Downloads every collection in the requirements file, plus its dependencies, as tarballs into a bundle directory. Nothing is installed and no plugin runs.
Process download dependency map
Starting collection download process to '/home/opsuser/project/bundle'
Downloading collection 'community.docker:4.7.0' to '/home/opsuser/project/bundle'
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-docker-4.7.0.tar.gz to /home/opsuser/.ansible/tmp/ansible-local-1971711zm7rmrd/tmpwnwtvy3l/community-docker-4.7.0-v3o6lid7
Collection 'community.docker:4.7.0' was downloaded successfully
Downloading collection 'community.library_inventory_filtering_v1:1.1.5' to '/home/opsuser/project/bundle'
Collection 'community.library_inventory_filtering_v1:1.1.5' was downloaded successfully
Writing requirements.yml file of downloaded collections to '/home/opsuser/project/bundle/requirements.yml'
The last line is the useful part. The bundle is self-describing:
Read-only / Safewhat a bundle contains— Lists the bundle directory. Two artefacts and a generated requirements file naming them.
$ ls -la ./bundle && cat ./bundle/requirements.yml
total 588
-rw-rw-r-- 1 opsuser opsuser 557525 Aug 11 22:36 community-docker-4.7.0.tar.gz
-rw-rw-r-- 1 opsuser opsuser 36002 Aug 11 22:36 community-library_inventory_filtering_v1-1.1.5.tar.gz
-rw-rw-r-- 1 opsuser opsuser 147 Aug 11 22:36 requirements.yml
collections:
- name: community-docker-4.7.0.tar.gz
version: 4.7.0
- name: community-library_inventory_filtering_v1-1.1.5.tar.gz
version: 1.1.5
Note what the generated file contains: filenames, not collection
names. That is a relative path, and it produces the most common
failure with this workflow.
Configuration changeinstall with no network at all— Installs from the bundle's own tarballs. Run from inside the bundle directory. Note the absence of any Downloading line.
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Installing 'community.docker:4.7.0' to '/home/opsuser/project/collections/ansible_collections/community/docker'
community.docker:4.7.0 was installed successfully
Installing 'community.library_inventory_filtering_v1:1.1.5' to '/home/opsuser/project/collections/ansible_collections/community/library_inventory_filtering_v1'
community.library_inventory_filtering_v1:1.1.5 was installed successfully
No Downloading lines. Nothing was fetched. This install will produce
byte-identical content on a machine with no route to the internet, in
five years, from the same bundle.
--offline on install means do not contact any distribution server.
It does not cover collections referenced by a git URL or a remote
tarball URL — those are still network operations, which is one more
reason a bundle should contain only artefacts.
Private Galaxy servers
The bundle is the air-gapped answer. For a connected estate that simply
wants control, the answer is a server you run: Automation Hub, a
Galaxy-compatible artefact repository, or a pull-through cache in
whatever artefact manager you already have for .deb and container
images.
The mechanics, from the setting’s own documentation:
server_list names sections. Each entry foo corresponds to a
[galaxy_server.foo] header holding that server’s details.
Order is resolution order. A collection is looked for in the
first server, then the second, and so on.
Setting server_list makes the single-server server setting
ignored entirely. There is no implicit fallback to public Galaxy
once you have a list — if you want it, it must be in the list, and
that is a decision worth making explicitly rather than inheriting.
Knowledge check
Knowledge check · 4 questions
Q1. A bundle built with ansible-galaxy collection download is copied to a disconnected host, and the install fails with "name is not an FQCN. Could not find community-docker-4.7.0.tar.gz". What is the cause?
Q2. Which are genuine problems with a pipeline that runs ansible-galaxy collection install from public Galaxy before every playbook run? Select all that apply.
Q3. An ansible.cfg sets server_list = internal_hub, community_mirror. What is the effect on the public Galaxy server?
Q4. A requirements file entry naming a git URL is still a network operation even when the install is run with --offline.
Passing score: 75%. Answers are checked in this browser.