AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible GitOps: Infrastructure as Code with Git Workflows and AAP

By Luca Berton · Published 2024-01-01 · Category: installation

Implement GitOps workflows with Ansible and AAP. Use Git as single source of truth for infrastructure, automate deployments with webhooks, and enforce change.

Introduction

GitOps is the practice of using Git as the single source of truth for infrastructure and configuration. Every change goes through a pull request, gets reviewed, and triggers automated deployment. When combined with Ansible Automation Platform, GitOps brings enterprise-grade change control to infrastructure automation.

See also: ARA Records Ansible: Playbook Reporting & History (Complete Guide)

GitOps Principles for Ansible

  1. Git is the source of truth — All playbooks, inventories, and variables live in Git
  2. Changes via pull requests — No manual changes; everything goes through code review
  3. Automated deployment — Merges to main trigger automatic AAP job execution
  4. Drift detection — Regular scans detect and remediate manual changes
  5. Audit trail — Git history + AAP job logs provide complete change history

Repository Structure

ansible-infrastructure/
├── inventories/
│   ├── production/
│   │   ├── hosts.yml
│   │   └── group_vars/
│   │       ├── all.yml
│   │       └── webservers.yml
│   └── staging/
│       ├── hosts.yml
│       └── group_vars/
├── playbooks/
│   ├── site.yml
│   ├── deploy-app.yml
│   ├── security-baseline.yml
│   └── patch-servers.yml
├── roles/
│   ├── common/
│   ├── webserver/
│   └── database/
├── collections/
│   └── requirements.yml
├── execution-environment/
│   ├── execution-environment.yml
│   └── requirements.txt
├── .github/
│   └── workflows/
│       ├── lint.yml
│       └── deploy.yml
├── ansible.cfg
├── ansible-lint.yml
└── README.md

Git Workflow

Branch Strategy

main (protected)
  ├── feature/add-monitoring
  ├── fix/ssh-config
  └── hotfix/security-patch

Pull Request Process

1. Developer creates branch
2. Makes changes to playbooks/roles
3. Opens pull request
   → Automated ansible-lint runs
   → Automated syntax check
   → Automated --check mode against staging
4. Peer review and approval
5. Merge to main
   → Webhook triggers AAP job
   → AAP deploys to production

See also: AAP 2.6 CI/CD Pipeline Integration: GitOps Workflows with Jenkins, GitLab, and GitHub Actions

AAP Webhook Integration

GitHub Webhook to AAP

Configure AAP to listen for GitHub webhooks:

  1. AAP: Job Template → Enable Webhook → Copy Webhook URL and Key
  2. GitHub: Repository → Settings → Webhooks → Add webhook
  3. URL: https://aap.example.com/api/v2/job_templates/42/github/
  4. Content type: application/json
  5. Secret: (from AAP webhook key)
  6. Events: Push events on main branch

Webhook Payload in Playbook

- name: Deploy from webhook trigger
  hosts: webservers
  vars:
    git_ref: "{{ awx_webhook_payload.ref | default('refs/heads/main') }}"
    commit_sha: "{{ awx_webhook_payload.after | default('HEAD') }}"
    committer: "{{ awx_webhook_payload.pusher.name | default('unknown') }}"
  tasks:
    - name: Log deployment trigger
      ansible.builtin.debug:
        msg: "Deploying {{ commit_sha[:8] }} by {{ committer }}"

    - name: Pull latest code
      ansible.builtin.git:
        repo: "{{ app_repo }}"
        dest: /opt/myapp
        version: "{{ commit_sha }}"
      notify: restart app

CI/CD Pipeline

GitHub Actions: Lint + Test

# .github/workflows/lint.yml
name: Ansible Lint & Test
on:
  pull_request:
    paths: ['playbooks/**', 'roles/**', 'inventories/**']

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install ansible-lint
        run: pip install ansible-lint yamllint

      - name: YAML Lint
        run: yamllint .

      - name: Ansible Lint
        run: ansible-lint playbooks/

      - name: Syntax Check
        run: ansible-playbook playbooks/site.yml --syntax-check

  dry-run:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Ansible
        run: pip install ansible-core

      - name: Dry Run against staging
        run: |
          ansible-playbook playbooks/site.yml \
            -i inventories/staging/hosts.yml \
            --check --diff
        env:
          ANSIBLE_HOST_KEY_CHECKING: "false"

Auto-Trigger AAP on Merge

# .github/workflows/deploy.yml
name: Deploy via AAP
on:
  push:
    branches: [main]

jobs:
  trigger-aap:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger AAP Job Template
        run: |
          curl -X POST \
            "https://aap.example.com/api/v2/job_templates/${{ secrets.AAP_TEMPLATE_ID }}/launch/" \
            -H "Authorization: Bearer ${{ secrets.AAP_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{"extra_vars": {"git_sha": "${{ github.sha }}"}}'

See also: Ansible Policy and Migration Engine (APME): AI-Powered Playbook Scanning and Compliance

Drift Detection

Schedule regular compliance scans to detect manual changes:

# drift-detection.yml
- name: Detect configuration drift
  hosts: all
  become: true
  tasks:
    - name: Check SSH config matches desired state
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        line: "PermitRootLogin no"
        state: present
      check_mode: true
      register: ssh_drift

    - name: Alert on drift
      ansible.builtin.debug:
        msg: "DRIFT DETECTED: SSH config changed on {{ inventory_hostname }}"
      when: ssh_drift.changed

    - name: Report drift to monitoring
      ansible.builtin.uri:
        url: "{{ alertmanager_url }}/api/v1/alerts"
        method: POST
        body_format: json
        body:
          - alertname: ConfigDrift
            labels:
              host: "{{ inventory_hostname }}"
              severity: warning
      when: ssh_drift.changed
      delegate_to: localhost

Encrypted Secrets in Git

# Encrypt sensitive variables with Ansible Vault
ansible-vault encrypt inventories/production/group_vars/all/vault.yml

# Use in CI/CD (vault password from secret)
ansible-playbook site.yml --vault-password-file <(echo "$VAULT_PASSWORD")

AAP Project Configuration

# AAP Project settings
Project:
  Name: Infrastructure GitOps
  SCM Type: Git
  SCM URL: https://github.com/myorg/ansible-infrastructure.git
  SCM Branch: main
  SCM Update on Launch: true  # Always pull latest
  SCM Clean: true

Job Template:
  Name: Deploy Infrastructure
  Project: Infrastructure GitOps
  Playbook: playbooks/site.yml
  Inventory: Production
  Credentials: [SSH Key, Vault Password]
  Webhook: Enabled (GitHub)

Best Practices

  1. Protect the main branch — Require PR reviews and passing CI checks
  2. Ansible-lint in CI — Catch issues before they reach production
  3. Check mode in PRs — Dry-run against staging on every pull request
  4. Encrypt secrets — Use Ansible Vault or HashiCorp Vault for sensitive data in Git
  5. Tag releases — Semantic versioning for infrastructure changes
  6. Automated rollback — If deployment fails, revert to previous Git tag
  7. Small, frequent changes — Easier to review and debug than large PRs
  8. Drift detection on schedule — Daily scans to catch manual changes

FAQ

How to handle emergency changes?

Create a hotfix/ branch, get expedited review (single approver), merge to main. The webhook triggers deployment immediately. Document the emergency in the commit message.

Can I use GitLab instead of GitHub?

Yes — AAP supports GitLab webhooks natively. The workflow is identical; just configure the GitLab project webhook URL from AAP.

How to rollback a bad deployment?

git revert HEAD  # Create a revert commit
git push origin main  # Webhook triggers deployment of reverted state

Conclusion

GitOps with Ansible and AAP creates an auditable, reviewable, automated infrastructure pipeline. Every change is tracked in Git, reviewed by peers, tested in CI, and deployed automatically — turning infrastructure management into a disciplined engineering practice.

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home