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: truefor 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.