How to run Ansible in CI/CD
Coming from another cloud?
▸AWS·Codepipeline With Ansible
This Quake AI feature maps to AWS’s Codepipeline With Ansible.
▸Azure·Pipelines With Ansible
This Quake AI feature maps to Azure’s Pipelines With Ansible.
How to run Ansible in CI/CD
This guide runs Ansible playbooks against Quake AI from GitHub Actions and GitLab CI. The same pipeline patterns drive scheduled patching, release deploys, and the Day 1 configuration step that follows an OpenTofu provision.
For the OpenTofu equivalent, see How to integrate OpenTofu with CI/CD. For the combined provision-and-configure flow, see How to use Ansible with OpenTofu on Quake AI.
Prerequisites#
- A working playbook that runs locally against Quake AI (see getting-started)
- Application credentials available as CI secrets, either as
clouds.yamlcontent or as the discreteOS_*variables. The same credentials drive the modules and the dynamic inventory plugin. - A GitHub or GitLab repository with the playbook and inventory committed
Secrets configuration#
Both CI platforms need the Quake AI authentication values stored as secrets. The minimum set:
| Variable | Purpose |
|---|---|
OS_AUTH_URL | Quake AI Keystone endpoint |
OS_APPLICATION_CREDENTIAL_ID | Application credential id |
OS_APPLICATION_CREDENTIAL_SECRET | Application credential secret |
OS_REGION_NAME | Region (for example us-east-1) |
OS_INTERFACE | public for most projects |
OS_IDENTITY_API_VERSION | 3 |
ANSIBLE_VAULT_PASSWORD | Optional: only if your playbook reads ansible-vault files |
SSH_PRIVATE_KEY | The key Ansible uses to reach managed hosts (PEM format) |
The OS_* variables shown above match the authentication chain the modules and the inventory plugin both read. CI runners typically prefer environment variables over a checked-in clouds.yaml.
GitHub actions#
Single-job playbook run#
The minimal pipeline installs Ansible plus openstacksdk, writes the SSH key to disk, and runs the playbook. Trigger on workflow_dispatch so production runs require an explicit click:
name: Configure infrastructure
on:
workflow_dispatch:
push:
branches: [main]
paths:
- "playbooks/**"
- "inventory/**"
jobs:
configure:
runs-on: ubuntu-latest
env:
OS_AUTH_URL: ${{ secrets.OS_AUTH_URL }}
OS_APPLICATION_CREDENTIAL_ID: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }}
OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }}
OS_REGION_NAME: ${{ secrets.OS_REGION_NAME }}
OS_INTERFACE: public
OS_IDENTITY_API_VERSION: "3"
ANSIBLE_HOST_KEY_CHECKING: "False"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Ansible and openstacksdk
run: |
pip install "ansible-core>=2.13" "openstacksdk>=1.0.0"
ansible-galaxy collection install openstack.cloud
- name: Write SSH key
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Run playbook
run: |
ansible-playbook \
-i inventory/openstack.yml \
--private-key ~/.ssh/id_ed25519 \
playbooks/site.ymlANSIBLE_HOST_KEY_CHECKING: "False" disables strict host key prompts that would otherwise hang in a non-interactive runner. For environments where strict checking is required, prepopulate ~/.ssh/known_hosts from a checked-in fixture instead.
Sequenced provision-then-configure#
The canonical Day 0 plus Day 1 pattern runs OpenTofu in one job and Ansible in a downstream job. The configure job depends on needs: provision, which guarantees order:
name: Deploy
on:
workflow_dispatch:
jobs:
provision:
runs-on: ubuntu-latest
env:
OS_AUTH_URL: ${{ secrets.OS_AUTH_URL }}
OS_APPLICATION_CREDENTIAL_ID: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }}
OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }}
OS_REGION_NAME: ${{ secrets.OS_REGION_NAME }}
steps:
- uses: actions/checkout@v4
- uses: opentofu/setup-opentofu@v1
- run: tofu -chdir=infra init
- run: tofu -chdir=infra apply -auto-approve
configure:
needs: provision
runs-on: ubuntu-latest
env:
OS_AUTH_URL: ${{ secrets.OS_AUTH_URL }}
OS_APPLICATION_CREDENTIAL_ID: ${{ secrets.OS_APPLICATION_CREDENTIAL_ID }}
OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }}
OS_REGION_NAME: ${{ secrets.OS_REGION_NAME }}
ANSIBLE_HOST_KEY_CHECKING: "False"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.11" }
- run: |
pip install "ansible-core>=2.13" "openstacksdk>=1.0.0"
ansible-galaxy collection install openstack.cloud
- name: Write SSH key
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- run: |
ansible-playbook \
-i inventory/openstack.yml \
--private-key ~/.ssh/id_ed25519 \
playbooks/site.ymlThe configure job uses the dynamic inventory plugin, which queries Quake AI directly. The provision job does not need to pass an inventory file forward: Ansible discovers the new instance through the metadata OpenTofu set on it. The full handoff (including the alternative tofu output -json path) is documented in How to use Ansible with OpenTofu on Quake AI.
GitLab CI#
GitLab pipelines fit the same shape. Use a Python or Ansible image, pull credentials from masked CI/CD variables, and gate production with when: manual:
stages:
- configure
variables:
ANSIBLE_HOST_KEY_CHECKING: "False"
OS_INTERFACE: public
OS_IDENTITY_API_VERSION: "3"
.ansible_base:
image: python:3.11-slim
before_script:
- apt-get update && apt-get install -y --no-install-recommends openssh-client
- pip install "ansible-core>=2.13" "openstacksdk>=1.0.0"
- ansible-galaxy collection install openstack.cloud
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
configure_staging:
extends: .ansible_base
stage: configure
script:
- ansible-playbook -i inventory/openstack.yml --private-key ~/.ssh/id_ed25519 playbooks/site.yml --limit env_staging
rules:
- if: $CI_COMMIT_BRANCH == "main"
configure_production:
extends: .ansible_base
stage: configure
script:
- ansible-playbook -i inventory/openstack.yml --private-key ~/.ssh/id_ed25519 playbooks/site.yml --limit env_production
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
environment:
name: productionIn GitLab, mark the secret variables (OS_*, SSH_PRIVATE_KEY) as Masked and Protected so they never appear in logs and only run on protected branches. Configure them under Settings > CI/CD > Variables in the project.
If you prefer a pre-baked Ansible runtime, swap python:3.11-slim for quay.io/ansible/awx-ee or another community Ansible image. The trade-off is image size against having ansible-core and openstacksdk already installed.
Secret management#
A few rules keep the pipeline credible:
- Never commit vault passwords, application credential secrets, or SSH private keys to the repository. Pipelines load them from the platform's secrets store.
- If a playbook reads
ansible-vault-encrypted files, supply the password through--vault-password-file <(echo "$ANSIBLE_VAULT_PASSWORD")rather than echoing the value into a file the runner does not clean up. - Rotate the application credential and the SSH private key on a schedule (every 90 days is a common cadence). Generate new ones, replace the secret values, and retire the old credential.
- Scope each pipeline to its own application credential. A leaked secret in a staging pipeline should not have permission to apply changes in production.
- Restrict who can trigger
workflow_dispatchruns and who can approve manual GitLab gates. The platform's secrets store is only as strong as the access control on the people who can call it.
Tear down#
The pipeline configurations themselves do not create persistent infrastructure. Removing them stops future runs but does not change anything on Quake AI. To roll back the configuration applied by the playbook, write a teardown playbook with state: absent tasks (the provisioning guide shows the pattern) and run it through the same pipeline.
See also#
- Ansible on Quake AI
- How to use Ansible with OpenTofu on Quake AI
- How to use Ansible dynamic inventory on Quake AI
- How to integrate OpenTofu with CI/CD
- How to deploy an application to a Quake AI VM from CI
- How to deploy to a Quake AI Kubernetes cluster from CI
- How to provision a Quake AI instance with Ansible
- Generate app credentials
Usage Guidelines
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.
For the full policy, see Usage Guidelines.
Last validated: 23.05.2026
Quick answers
See Also
CI/CD pipelines
Related
How to use Ansible dynamic inventory on Quake AI
Shares: Ansible, Configuration Management
How to provision a Quake AI instance with Ansible
Shares: Ansible, Configuration Management
Automation / IaC FAQ
Shares: Cicd, Ansible
Use Ansible with OpenTofu on Quake AI
Shares: Cicd, Ansible