Pass Environment Variables from GitLab CI to Ansible Shell

5 min read.
Tags: devopsgitlabci-cdansible

Passing environment variables from GitLab CI to Ansible shell tasks is straightforward once you stop relying on export inside previous tasks.

The key point: every Ansible task runs in its own process. So an export in task A does not automatically exist in task B.

Why variables disappear between Ansible shell tasks

This pattern looks correct, but it is not persistent:

- name: Set token
  shell: |
    export APP_TOKEN=my-token

- name: Use token
  shell: |
    echo "$APP_TOKEN"

APP_TOKEN will be empty in the second task.

For GitLab CI pipelines, pass the value directly from CI variables to Ansible and inject it where needed.

Pass GitLab CI variables to ansible-playbook

Define CI variable in GitLab (Settings > CI/CD > Variables), then pass it as extra-vars:

deploy:
  stage: deploy
  image: python:3.12
  variables:
    ANSIBLE_HOST_KEY_CHECKING: "False"
  script:
    - pip install ansible
    - ansible-playbook -i inventory.ini deploy.yml -e "app_token=$APP_TOKEN"

$APP_TOKEN here is provided by GitLab CI. Mark it as Masked and Protected if it is sensitive.

Use that variable in Ansible shell task

Use task-level environment so the shell command receives it as env var:

- name: Run deploy script with token
  shell: ./deploy.sh
  args:
    chdir: /opt/my-app
  environment:
    APP_TOKEN: "{{ app_token }}"

Inside deploy.sh, you can safely access:

#!/usr/bin/env bash
set -euo pipefail

curl -H "Authorization: Bearer $APP_TOKEN" https://api.example.com/deploy

This is much clearer than trying to carry export state across multiple tasks.

Alternative: read from environment inside Ansible

If you prefer, read environment directly in playbook:

- name: Use CI variable directly
  shell: ./deploy.sh
  environment:
    APP_TOKEN: "{{ lookup('env', 'APP_TOKEN') }}"

This works when the runner process already has APP_TOKEN exported. In GitLab CI jobs, it usually does.

Security notes

For secrets in GitLab CI and Ansible:

  • store secret as Masked + Protected variable in GitLab
  • avoid printing secret values in logs (echo $APP_TOKEN)
  • use no_log: true for tasks that may expose sensitive output

Example:

- name: Deploy with secret token
  shell: ./deploy.sh
  environment:
    APP_TOKEN: "{{ app_token }}"
  no_log: true

Conclusion

To pass environment variables from GitLab CI to Ansible shell tasks, send them through -e or lookup('env', ...), then inject with task-level environment. Do not depend on export from earlier shell tasks because that state is not persisted.

Related Posts