unit 6 · Making it real

Galaxy, requirements.yml & pinning

The lockfile instinct, ported

essential · 6 min · linux + windows

you may want to read 4 · Collections & FQCN , 24 · Roles: structure, defaults vs vars first — but nothing is locked

tl;dr

  • ansible-galaxy installs collections and roles; requirements.yml is the manifest a project commits.
  • One command restores every dependency: ansible-galaxy install -r requirements.yml.
  • Pin versions — unpinned installs grab whatever is latest that day, and machines drift apart.

why it matters Clone a repo, run the playbook, fail on a missing collection — requirements.yml is how real projects turn "install what this needs" into one reproducible command.

Lesson 4 left you with one command: ansible-galaxy collection install community.general. It works, and it’s also a trap: it installs whatever version is latest today, onto your machine only. Fine for a laptop experiment; useless as a team workflow. This lesson covers where that command reaches, how a project declares its needs in one committed file, and why the version pin saves you.

The command talks to Galaxy — Ansible’s public hub at galaxy.ansible.com for collections and community roles — via the ansible-galaxy CLI. Two install verbs cover both kinds of content:

ansible-galaxy collection install community.general   # a collection, from lesson 4
ansible-galaxy role install geerlingguy.nginx         # a standalone role from the hub
two verbs: one for collections, one for standalone roles

The second verb matters because Galaxy predates collections: thousands of standalone roles (lesson 24’s unit of reuse) live there under author.rolename names, and plenty of teams still consume them directly.

The manifest: requirements.yml

A real repo doesn’t document dependencies in a README. It commits a manifest named requirements.yml:

# requirements.yml
collections:
  - name: ansible.windows
    version: 3.5.0             # exact pin — every install identical
  - name: community.general    # unpinned — grabs latest today (avoid)
roles:
  - name: geerlingguy.nginx    # roles list the same way, version: included
one manifest, two kinds of dependency

The shape is what you see: a collections: list and a roles: list, each entry a dict with name: and — always, in a repo you respect — version:. One command installs everything the file names:

ansible-galaxy install -r requirements.yml   # installs both lists
restore everything a project needs

That command is how a fresh clone becomes runnable. You’ll meet it again verbatim in lesson 41: the Jenkins pipeline pattern starts this way — check out the repo, ansible-galaxy install -r requirements.yml, run the playbook. The CI agent starts empty every time; the manifest makes that a feature instead of a failure.

In the standard repo layout (lesson 36) you’ll usually find the manifest split in two — collections/requirements.yml and roles/requirements.yml — same shape, one kind of content per file.

Pin it

An unpinned entry means “latest at the moment of install.” You installed in March, the CI agent installs tonight, the new teammate installs in August: three collection versions, one Git commit, and a bug that reproduces on only one machine. You already own the instinct that prevents this — it’s a lockfile. The same reflex that pins a Docker base image to a real tag instead of :latest applies here: exact version: pins, upgraded deliberately in a reviewed commit, never as a side effect of install day.

Pinning also connects this file to the execution-environment world of lesson 40. There, dependencies get baked into a container image at build time instead of installed on the control node — but they’re built from this same manifest. Either way the habit is identical: the moment a playbook uses a collection outside the bundle from lesson 5, it goes into requirements.yml with a version — not just into your machine’s collection path. The next person to clone the repo is counting on it, and so is the CI runner that deploys it.

self-check — recall, not a test

  1. 1 A teammate’s playbook fails with a module-not-found error on ansible.windows.win_service. What do you look for in the repo, and what do you run?

  2. 2 Your playbook works, CI fails, a teammate sees a third behavior — all running the same Git commit. What dependency mistake produces this?

  3. 3 A repo has both collections/requirements.yml and roles/requirements.yml. Why does running only ansible-galaxy collection install -r leave you broken?

lab (optional — never required)

Write a requirements.yml pinning community.general to an exact version, install with ansible-galaxy install -r, then confirm the version with ansible-galaxy collection list.

needs: The control node from lesson 5.

next up 27 · Ansible Vault & vault IDs 8 min · unit 7