# "ansible-galaxy collection download" always downloads?

**URL:** <https://forum.ansible.com/t/ansible-galaxy-collection-download-always-downloads/44870>\
**Category:** Get Help\
**Tags:** galaxy-ng\
**Created:** [November 20, 2025, 10:54am UTC](https://forum.ansible.com/t/ansible-galaxy-collection-download-always-downloads/44870 "2025-11-20T10:54:24Z")\
**Posts on this page:** 1\
**Showing post:** 9

<div class="post-metadata">

**Author:** ![dnmvisser](https://avatars.discourse-cdn.com/v4/letter/d/8e8cbc/32.png) [@dnmvisser](https://forum.ansible.com/u/dnmvisser)\
**Post date:** [October 27, 2026, 8:24am UTC](https://forum.ansible.com/t/ansible-galaxy-collection-download-always-downloads/44870/9 "2026-10-27T08:24:42Z")

</div>

I ended up writing some shell wrapper to iterate over the galaxy requirements and storing the content locally first. Once done, any subsequent run will use the cached content. This saves time/resources, and also avoids dependencies on [galaxy.ansible.com](http://galaxy.ansible.com) (which may not always be online). Note that this does not do dependency resolution, but that is OK in our case as we have listed everything statically in the `ansible_galaxy.yml` file.  
Boilerplate:

```bash
#!/usr/bin/env bash

# Check for ansible_galaxy.yml file
GALAXY_REQS="ansible_galaxy.yml"

usage() {
  local script_name
  script_name=$(basename "$0")
  cat <<EOF
Usage: ${script_name} [-h|--help]

Cache and install Ansible Galaxy collections defined in ${GALAXY_REQS}.

Options:
  -h, --help Display this help message and exit
EOF
}

for arg in "$@"; do
  case "$arg" in
    -h|--help)
      usage
      exit 0
      ;;
  esac
done

# Check for required tools
for cmd in yq jq ansible-galaxy python3; do
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Error: Required command '${cmd}' not found in PATH." >&2
    exit 1
  fi
done

if [! -r "${GALAXY_REQS}"]; then
  echo "No readable ansible_galaxy.yml file found, but we do need one.
Exiting"
  exit 1
fi

# Set commands
PYTHON="python3"
GALAXY="ansible-galaxy"

# Galaxy part
function install_galaxy_requirements() {

  CACHE_DIR="${HOME}/.cache/galaxy"
  if [! -d "$CACHE_DIR"]; then
    mkdir -p "$CACHE_DIR"
  fi

  # Start with empty data structure, to build a local requirements file
  TEMP_REQS="$(mktemp).yml"
  echo -e "---\ncollections: []" > "${TEMP_REQS}"

  # Iterate over requirements
  yq -rc '.collections[]' "${GALAXY_REQS}" | while read -r item; do
    NAME=$(jq -r '.name' <<< "$item")
    SOURCE=$(jq -r '.source // "https://galaxy.ansible.com"' <<< "$item")
    VERSION=$(jq -r '.version' <<< "$item")
    CACHE_FILE="${CACHE_DIR}/${NAME/./-}-${VERSION}.tar.gz"
    if [! -f "${CACHE_FILE}"]; then
      # Download collection
      "$GALAXY" collection download \
        --server "${SOURCE}" \
        --download-path "${CACHE_DIR}" \
        "${NAME}:${VERSION}"
    else
      echo "Collection $NAME is available in cache, not downloading it"
    fi

    # Append item to collection list in the cached requirements file.
    # For the "name" we use the absolute path to the tarball
    yq --yaml-output --in-place \
      --arg name "$(realpath "${CACHE_DIR}")/${NAME/./-}-${VERSION}.tar.gz" \
      --arg version "${VERSION}" \
      '.collections += [{name: $name, version: $version}]' \
      "${TEMP_REQS}"
  done

  # Now install from the cached requirements file
  ANSIBLE_COLLECTIONS_PATH=$("${PYTHON}" -c "import site; print(site.getsitepackages()[0])") \
    "$GALAXY" collection install -r "${TEMP_REQS}"

  # Remove temp requirements file
  rm -f "${TEMP_REQS}"
}

# Install the collections
install_galaxy_requirements

```

---

_[View the full topic](https://forum.ansible.com/t/ansible-galaxy-collection-download-always-downloads/44870)._
