Inventory and playbooks live in different GitLab groups/repos: far more scalable for a real environment.
Playbook repo (flat, dependencies at the root):
playbooks/<automation>/ # one repo per automation
βββ <playbook>.yml
βββ collections/requirements.yml # external collections
βββ roles/requirements.yml # only if it uses external roles
βββ templates/
Inventory repo (hosts + their variables):
inventories/<env>/
βββ <type>/
βββ <inventory>.yml # hosts + groups
βββ group_vars/<group>.yml # variables for that group
IMPORTANT
collections/requirements.yml (and roles/requirements.yml) must sit at the repo root: AWX installs Galaxy deps only from there, never from subfolders.
Then for wiring everything together (credential, Projects, Inventory Source, Job Template) you can check out how to Connect AWX to GitLab, it pairs with the AWX and GitLab guides.
How to use it
Two ways to run a playbook: from the command line, or via AWX pulled from GitLab (the βreal productionβ approach). Expand the one you need.
With Ansible CLI
One-time prerequisites on your control node
# Ansible itself + the collections the playbook usessudo apt install -y ansibleansible-galaxy collection install <collection> # e.g. community.general# or, if the repo ships one:ansible-galaxy collection install -r collections/requirements.yml
Dry-run first (always)
ansible-playbook <playbook>.yml --check --diff
Shows what would change without applying. Always do this first on a new host β especially for anything touching SSH, PAM or the firewall β and read the diff before committing.
The playbook lives in GitLab and is pulled by an AWX Project β see Connect AWX to GitLab for the wiring. The CLI flags above map directly onto Job Template fields.
Set up the Job Template β Resources β Templates β Add β Job Template:
Project: your playbook project Β· Playbook: <path>/<playbook>.yml(dropdown; subfolders are listed too)
Inventory: one that contains the group the playbook targets (hosts: <group>)
Credentials: the Machine credential for the targets
Execution Environment: leave default(itβs the runtime image, not a machine)
Instance Groups: execution-vms(the execution node β the machine that SSHes to the targets)
Dry-run first (always) β set Job Type β Check and enable Show Changes (= --check --diff). Launch once and read the diff before a real run.
Apply β set Job Type β Run β Launch.
Run only part of it (tags) β use the Job Tags / Skip Tags fields (tick Prompt on launch to choose per-run).
Limit to specific hosts β the Limit field (same as --limit).
Override variables β pass them in the Job Templateβs Variables (extra vars), or β nicer β expose them as a Survey (a field/checkbox per option):
<var>: <value>
Execution Environment β Execution Node EE = the container image the job runs in β leave it default. Execution Node = the machine that runs the job and SSHes to the target β chosen via Instance Groups. Don't confuse the two (and don't pick "Control Plane Execution Environment").
Same cautions as the CLI: dry-run on a new host first, and be careful with destructive/irreversible changes until youβve verified the diff.