This guide wires GitLab into AWX so that inventories, playbooks, roles and collections all live in versioned, reviewable Git reposI.

Git becomes the single source of truth: AWX just mirrors it.


The model: one mechanism, two consumers

A Project in AWX = a Git repo, cloned and kept in sync.

Its a live link, not a one-time import.

Basically, we can create a project that will contain our inventories, and another one for our playbooks, and link everything together to make it run.

flowchart LR
    subgraph GL["🦊 GitLab"]
        PB["automation/playbooks<br/>site.yml + roles/ + collections/"]
        INV["inventories/prod<br/>openstack/openstack.yml + group_vars/"]
    end
    subgraph AWX["πŸŽ›οΈ AWX"]
        ProjPB["πŸ“š Project (playbooks)"]
        ProjINV["πŸ“š Project (inventories)"]
        Src["πŸ”— Inventory Source"]
        Inv["πŸ“‹ Inventory"]
        JT["▢️ Job Template<br/>Project + Playbook + Inventory"]
    end
    Target["πŸ–₯️ target hosts"]
    PB -- "git clone" --> ProjPB
    INV -- "git clone" --> ProjINV
    ProjINV --> Src
    Src -- "sync = import" --> Inv
    ProjPB --> JT
    Inv --> JT
    JT -- "run via execution node" --> Target
  • Job Templates pick a playbook from inside a Project
  • Inventory Sources pick an inventory file from a Project
  • roles / collections come in through requirements.yml, automatically on Project sync.

INFO

A green Sync Status: Success on an inventory, or a Job Template that just has a playbook dropdown, both mean the same thing underneath: a Project (Git) behind it.


1. GitLab: the repos

First we have to create Groups:

This is my Inventories group, it contains projects organized per environment (prod, test, dev…), and every project contain its inventory file + group_vars/ together.

For example:

inventories/prod # inventories is the group, prod is the project 
└── openstack/ # openstack is just a folder
    β”œβ”€β”€ openstack.yml # this is the inventory file 
    └── group_vars/all.yml # these are the group_vars
inventories/test
└── openstack/
...

IMPORTANT

Keep group_vars/ in the same folder as the inventory file, that’s how Ansible (and AWX’s import) auto-loads them.

This is my Automation group, it contains a Playbooks project, that contains many folders for dedicated playbooks, for example:

automation/playbooks
└── UpgradeHost/
	β”œβ”€β”€ upgrade.yml
	β”œβ”€β”€ roles/requirements.yml         # external roles (Galaxy or Git)
	└── collections/requirements.yml   # external collections
└── JoinAD/
...

2. GitLab: read-only SSH access (one credential for all repos)

AWX only needs to clone.

To do that, we can use a read-only service account with a dedicated SSH key, member of every group: this way one credential can clone every repo.

Procedure:

  1. Bot user: Admin β†’ Users β†’ New user β†’ svc-awx.
  2. Read access: each group (inventories, automation…) β†’ Manage β†’ Members β†’ Invite β†’ svc-awx β†’ role Reporter.
  3. Create a SSH key:
    ssh-keygen -t ed25519 -f svc-awx -C svc-awx -N ""
  4. Admin β†’ Users β†’ svc-awx β†’ Impersonate β†’ Preferences β†’ SSH Keys β†’ paste svc-awx.pub β†’ Stop impersonation.

Besides the key we just created for syncing projects and inventories, every target needs:

  • A key for letting in the execution nodes via SSH (that you will select later in AWX when running the playbook): the public half goes in the target’s ~/.ssh/authorized_keys, while the private half stays in every execution nodes. You can of course recycle it for every target: you just need to create it in a execution node, and do ssh-copy-id -i awx_target.pub <user>@<target-ip> (and of course you also need to put the private key inside every other execution node that you have).
  • Every target allowing :22 from the execution node’s IP as source.

3. AWX: Source Control credential (SSH)

Resources β†’ Credentials β†’ Add

  • Credential Type: Source Control

  • SCM Private Key: the private svc-awx key

  • Leave Username / Password / Passphrase empty (the user comes from the git@ URL).


4. AWX: one Project per repo

Create a Project for each repo: same steps, different URL.

Resources β†’ Projects β†’ Add:

FieldPlaybooksInventories
NamePlaybooksInventories
Source Control TypeGitGit
Source Control URLgit@gitlab.yourdomain.com:automation/playbooks.gitgit@gitlab.yourdomain.com:inventories/prod.git
Source Control Credentialsvc-awxsvc-awx
Optionsβœ… Update Revision on Launchβœ… Update Revision on Launch

For the Source Control URL, you have to copy the exact SSH URL from the GitLab repo’s Code β†’ Clone with SSH.

Save each, and wait for Successful.

Ok, so now your AWX can see inventories and playbooks from your GitLab.

Now let’s see how to actually put everything together in AWX:

  • Inventories in a inventory source
  • Playbooks in a job template

And combine them to make everything work and run.


Inventories β†’ Inventory + Source

Resources β†’ Inventories β†’ Add β†’ Inventory β†’ Name β†’ Save (this is just an empty container for now).

Now open it: Sources tab (appears only after saving) β†’ Add:

FieldValue
SourceSourced from a Project
ProjectInventories
Inventory fileopenstack/openstack.yml (in this example) (not the same as screenshot)
Optionsβœ… Update on launch Β· βœ… Overwrite Β· βœ… Overwrite variables

Save β†’ Sync.


Playbooks β†’ Job Template

This is the main use of a Project.

Resources β†’ Templates β†’ Add β†’ Job Template:

FieldValue
NameThe name of the job Template
Job TypeRun
InventoryOpenStack (from the one we just created)
ProjectPlaybooks
PlaybookplaybookName.yml (dropdown, auto-detected)
Credentialsthe Machine credential for the targets
Instance Groupsexecution-vms (run on the execution node)

Save β†’ Launch.


Scaling out

Git stays the single source of truth, AWX has to mirror it:

  • playbooks GitLab repo β†’ AWX Project β†’ create many Job Templates
  • inventories GitLab repo β†’ AWX Project β†’ add many Inventory Sources (one per type: openstack/, windows/…)