Ansible Git and VS Code Workflow: Clone, Edit, Commit, and Run Playbooks

Set up a practical Ansible Git and VS Code workflow on Rocky Linux—clone a repo, edit YAML safely, commit playbooks, ignore secrets and cache files, run ansible-playbook from the integrated terminal, lint with ansible-lint, and optionally use Ansible Navigator.

Published

Updated

Read time 14 min read

Reviewed byDeepak Prasad

Ansible project opened in Visual Studio Code with Git, YAML editing, and terminal on Rocky Linux

Most Ansible work is editing YAML, running playbooks, and sharing changes with a team. Git tracks what changed; Visual Studio Code gives you syntax-aware editing and a terminal in the same window. Together they form a workflow that scales beyond exam labs—clone a repo, edit playbooks safely, commit configuration, and run ansible-playbook without leaving the editor.

This guide walks through that workflow on Rocky Linux 10: project layout, git clone, VS Code setup, .gitignore rules for Ansible artifacts, vault password file hygiene, ansible-lint, and a short Ansible Navigator example. It does not replace a full Git branching tutorial, a complete Vault guide, or deep execution environment configuration—those have dedicated pages.

Tested on: Rocky Linux 10.2 (Red Quartz); kernel 6.12.0-211.16.1.el10_2.0.1.x86_64; ansible-core 2.16.16; ansible-lint 26.6.0; ansible-navigator 26.6.0.

NOTE
This chapter is part of the GoLinuxCloud Ansible tutorial (RHCE EX294). Follow along from ~/ansible-project, inventory group lab, and playbooks in playbooks/. Use your own host names and paths if yours differ.
IMPORTANT
This article covers day-to-day Git + VS Code workflow for Ansible projects: clone, edit, commit, ignore generated files, and run playbooks from the integrated terminal. It does not cover advanced Git (rebasing, release branches), enterprise secret managers, full Vault operations, or building custom execution environments.

What This Article Covers

Topic In scope
Recommended project layout ansible.cfg, inventory/, playbooks/, roles/, requirements.yml
Git basics for Ansible repos clone, status, diff, add, commit
VS Code on Rocky Linux Install, open folder, extensions
Safe YAML editing Spaces, schema hints, FQCN habits
.gitignore for Ansible .retry, .cache/, vault password files
Run from integrated terminal ansible-playbook, --syntax-check
Quality checks ansible-lint from project root
Optional Navigator ansible-navigator run --mode stdout

Why Use Git and VS Code for Ansible Projects?

Ansible projects are folders of text files. Without version control, you cannot see who changed inventory/hosts, roll back a broken playbook, or onboard a teammate with one git clone.

VS Code complements Git on the control node:

  • Ansible extension (Red Hat) — playbook intelligence via ansible-language-server: module documentation, validation, and run helpers.
  • YAML extension — indentation and schema-aware editing for playbooks and vars files; pair with YAML syntax habits.
  • Integrated terminal — same working directory as the open folder, so ansible.cfg resolves correctly when you run playbooks.
  • Source Control view — stage and commit without memorizing every Git flag (still learn git status and git diff).

Ansible Navigator is separate: it is built to run and review Ansible content, including execution-environment workflows, not to replace the editor. Use Navigator when you want its TUI or stdout wrapper around ansible-playbook—details in run Ansible playbooks with navigator.


Prerequisites on Rocky Linux

On the control node you need:

Requirement Notes
Rocky Linux 10 (or RHEL-family) with GUI or VS Code on your laptop + SSH Desktop: install code on the VM. Laptop: Remote - SSH to the control node.
Ansible installed ansible-core 2.16+ tested
Git dnf install git -y
ansible user with project directory ~/ansible-project in this course
Optional ansible-lint, ansible-navigator via pip or dnf

Confirm Ansible from any directory first:

bash
ansible --version

Sample output:

output
ansible [core 2.16.16]
  config file = /etc/ansible/ansible.cfg
  ...

After you cd ~/ansible-project, the config file line should show your project ansible.cfg instead of /etc/ansible/ansible.cfg.


Open the repo root in VS Code—the directory that contains ansible.cfg. A practical tree matches the project directory structure guide:

text
~/ansible-project/
├── ansible.cfg
├── ansible-navigator.yml   # optional
├── inventory/
│   ├── hosts
│   ├── group_vars/
│   └── host_vars/
├── playbooks/
├── roles/
├── requirements.yml
├── README.md
└── .gitignore

Create missing folders once:

bash
mkdir -p ~/ansible-project/{inventory/group_vars,inventory/host_vars,playbooks,roles}

List the tree:

bash
find ~/ansible-project -print | sort

Sample output:

output
/home/ansible/ansible-project
/home/ansible/ansible-project/ansible.cfg
/home/ansible/ansible-project/inventory
/home/ansible/ansible-project/inventory/group_vars
/home/ansible/ansible-project/inventory/host_vars
/home/ansible/ansible-project/inventory/hosts
/home/ansible/ansible-project/playbooks
/home/ansible/ansible-project/roles
/home/ansible/ansible-project/requirements.yml

Git does not track empty directories. If you want to keep empty folders such as roles/, inventory/group_vars/, or inventory/host_vars/ in the repo before adding files, create a placeholder such as .gitkeep:

bash
touch roles/.gitkeep inventory/group_vars/.gitkeep inventory/host_vars/.gitkeep

Stage the placeholders with your first commit:

bash
git add roles/.gitkeep inventory/group_vars/.gitkeep inventory/host_vars/.gitkeep

Clone an Ansible Project Repository

If the project already lives in Git (GitHub, GitLab, internal Gitea), clone it to the control node:

bash
cd ~
git clone https://example.com/team/ansible-project.git
cd ansible-project

Replace the URL with your remote. For a local bare repo on the same host (lab simulation):

bash
git clone /path/to/ansible-project.git ~/ansible-project

List cloned files:

bash
ls

Sample output:

output
ansible.cfg  inventory  playbooks  requirements.yml

Install collections after clone so playbooks match the repo:

bash
ansible-galaxy collection install -r requirements.yml

Open the Project in VS Code

Install VS Code on Rocky Linux (desktop session)

From the official VS Code Linux documentation, import the Microsoft signing key:

bash
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc

Create /etc/yum.repos.d/vscode.repo:

bash
sudo tee /etc/yum.repos.d/vscode.repo << 'EOF'
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF

Install:

bash
sudo dnf install code -y

On Ubuntu laptops, use install VS Code on Ubuntu instead.

Open the folder

Log in as the ansible user, then:

bash
cd ~/ansible-project
code .

In VS Code, confirm the Explorer shows ansible.cfg, inventory/, and playbooks/ at the top level. If you only opened a single file, File → Open Folder and choose the repo root—otherwise the integrated terminal may start in the wrong directory and Ansible will not load your project config.


Install Useful VS Code Extensions

Open the Extensions view (Ctrl+Shift+X) and install:

Extension ID Purpose
Ansible redhat.ansible Language support via ansible-language-server, module docs, playbook run integration
YAML redhat.vscode-yaml Indentation, document structure, optional schema validation
GitLens (optional) eamodio.gitlens Blame and history inline—helpful on shared playbooks

After install, reload the window if prompted. Point the Ansible extension at your project when it asks for ansible.cfg, or set ansible.python.interpreter and validation paths in workspace settings if binaries are non-standard.

You do not need deep language-server tuning for daily EX294 work—defaults plus a correct project root are enough.

You can ignore local .vscode/settings.json in .gitignore (per-user paths and interpreter choices), but optionally commit .vscode/extensions.json so teammates get extension recommendations when they open the repo:

json
{
  "recommendations": [
    "redhat.ansible",
    "redhat.vscode-yaml"
  ]
}

VS Code prompts to install recommended extensions from that file—handy for onboarding without dictating personal editor settings.


Edit YAML Playbooks Safely in VS Code

Ansible playbooks are YAML. Common editor mistakes become runtime failures:

  • Use spaces, not tabs — YAML treats tabs as syntax errors.
  • Indent consistently — two spaces per level is the usual convention.
  • Prefer FQCNansible.builtin.debug instead of bare debug (see modules and ansible-doc).
  • Save before run — the terminal executes the file on disk, not unsaved buffer content.

Create playbooks/hello-vscode.yml:

yaml
---
- name: VS Code workflow demo
  hosts: lab
  gather_facts: false
  tasks:
    - name: Greet from playbook edited in VS Code
      ansible.builtin.debug:
        msg: "Hello from ansible-project"

Validate syntax from the terminal before your first real run:

bash
ansible-playbook playbooks/hello-vscode.yml --syntax-check

Sample output:

output
playbook: playbooks/hello-vscode.yml

Use the Integrated Terminal

Open Terminal → New Terminal (Ctrl+``). The prompt should show your project path, for example ~/ansible-project`.

If the path is wrong, click the + dropdown → Select Default Profile, then open a new terminal, or run:

bash
cd ~/ansible-project

Every ansible, ansible-playbook, ansible-lint, and ansible-navigator command in this guide assumes that working directory. ansible.cfg is discovered from the current directory—not from whichever file tab is active in the editor.


Run Basic Ansible Commands from VS Code

Ping inventory hosts:

bash
ansible lab -m ansible.builtin.ping

Run the demo playbook:

bash
ansible-playbook playbooks/hello-vscode.yml

Sample output:

output
PLAY [VS Code workflow demo] ***************************************************

TASK [Greet from playbook edited in VS Code] ***********************************
ok: [rocky2] => {
    "msg": "Hello from ansible-project"
}

PLAY RECAP *********************************************************************
rocky2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Use the same flags as on a plain SSH session: --check, --limit rocky2, -v for verbosity. The playbook runner guide covers check mode, diff, and tags.

Optional: Ctrl+Shift+PAnsible: Run Ansible Playbook and pick a file. The integrated terminal method is the one to know for exams and scripts.


Track Changes with Git

Initialize a new repo when you built the tree locally and there is no remote yet:

bash
cd ~/ansible-project
git init -b main

Check what Git sees:

bash
git status

Sample output (before first commit):

output
On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	ansible.cfg
	inventory/
	playbooks/
	requirements.yml

Add, Commit and View Changes

Stage project files:

bash
git add ansible.cfg inventory/hosts playbooks/ requirements.yml .gitignore
git commit -m "Initial ansible project layout"

Add a second playbook and inspect the diff:

bash
git add playbooks/site.yml
git diff --cached --stat

Sample output:

output
playbooks/site.yml | 2 ++
 1 file changed, 2 insertions(+)

Commit:

bash
git commit -m "Add site.yml wrapper playbook"

View history:

bash
git log --oneline -3

Sample output:

output
997ad4d Add site.yml wrapper playbook
fd53780 Initial ansible project layout

Use VS Code's Source Control panel for the same operations when you prefer clicks—but run git status and git diff from the terminal regularly so you are not lost without the UI.


Create a Useful .gitignore for Ansible

Add .gitignore at the repo root before the first push. Suggested starter (aligned with ansible-lint caching guidance):

gitignore
# Ansible generated files
*.retry
.cache/

# Python/cache
__pycache__/
*.pyc

# Vault password files and local secrets
.vault-pass
vault.pass
*.vault-password
.env

# Local editor/OS files
.vscode/settings.json
.DS_Store

ansible-lint documentation recommends ignoring .cache/ because the directory is recreated automatically.

Adding a path to .gitignore does not untrack a file Git already committed. If a secret was pushed by mistake, remove it from the index with git rm --cached <file>, add the path to .gitignore, commit that change, and rotate the secret—it may still exist in Git history.

Verify ignored paths:

bash
grep -E 'retry|cache|vault' .gitignore

Sample output:

output
*.retry
.cache/
.vault-pass
vault.pass
*.vault-password

Exclude Vault Password Files and Secrets

Ansible Vault encrypts sensitive content, but the password that decrypts it must never land in Git. Official Vault documentation stresses supplying vault secrets carefully—password files need restrictive permissions and must not be added to source control.

Create an empty password file with mode 600 (no password on the command line—echo would leave the secret in shell history):

bash
install -m 600 /dev/null .vault-pass

Type the password in an editor:

bash
vi .vault-pass

Or prompt without echoing to the terminal (still avoid logging the password in shell history on shared systems):

bash
read -s -p "Vault password: " VAULT_PASS

Press Enter, then write the file and clear the variable:

bash
printf '\n'
printf '%s\n' "$VAULT_PASS" > .vault-pass
chmod 600 .vault-pass
unset VAULT_PASS

Check Git status:

bash
git status --short

Sample output:

An empty status means .vault-pass is ignored—good. If Git lists .vault-pass as untracked, add the filename to .gitignore immediately and never commit it.

Point Ansible at the file for ad hoc runs (do not commit this path into shared ansible.cfg if it exposes a teammate-specific location—use per-user config or environment variables instead):

bash
ansible-playbook playbooks/site.yml --vault-password-file .vault-pass

Store Encrypted Vault Files Safely

Encrypted variable files—$ANSIBLE_VAULT;1.1;AES256 headers—are usually safe to commit because they are ciphertext. Reviewers still see that secrets exist, so use descriptive names (vault_db_password) and the vault_ prefix pattern from the Vault with group_vars guide.

Item Commit?
group_vars/lab/vault.yml (encrypted) Usually yes
Plain-text group_vars/lab/secrets.yml No—encrypt first
.vault-pass / vault.pass Never

Full encrypt, edit, and rekey workflows live in the Ansible Vault tutorial—this page only covers Git hygiene around vault passwords.


Run ansible-lint from the Project Directory

ansible-lint catches risky YAML, deprecated syntax, and policy violations before CI or peers see your commit. From the project root:

bash
ansible-lint playbooks/hello-vscode.yml

Sample output:

output
Passed: 0 failure(s), 0 warning(s) in 1 files processed of 1 encountered. Last profile that met the validation criteria was 'production'.

Lint the whole playbooks tree before a commit when you touch multiple files:

bash
ansible-lint playbooks/

Enable the Ansible extension's lint integration in settings if you want inline squiggles—CLI lint from the terminal matches what many pipelines run.


Use Ansible Navigator for Project Runs

Ansible Navigator wraps playbook execution with a TUI or plain stdout mode and optional execution environments. It does not replace VS Code for editing; use it when you want Navigator's run UI or EE workflow from the same project directory.

Stdout mode (script- and SSH-friendly):

bash
ansible-navigator run playbooks/hello-vscode.yml --mode stdout --ee false

Sample output:

output
PLAY [VS Code workflow demo] ***************************************************

TASK [Greet from playbook edited in VS Code] ***********************************
ok: [localhost] => {
    "msg": "Hello from ansible-project"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

On small lab VMs without container tooling, --ee false skips execution-environment images and uses local ansible-core—same idea as execution-environment.enabled: false in ansible-navigator.yml. Interactive TUI mode needs a real terminal: ansible-navigator run playbooks/hello-vscode.yml.


Common Examples

Clone a project and open it in VS Code

bash
cd ~
git clone https://example.com/team/ansible-project.git
cd ansible-project
code .

Create a playbook and commit it

bash
cd ~/ansible-project
cat > playbooks/hello-vscode.yml << 'EOF'
---
- name: VS Code workflow demo
  hosts: lab
  gather_facts: false
  tasks:
    - name: Greet from playbook edited in VS Code
      ansible.builtin.debug:
        msg: "Hello from ansible-project"
EOF
git add playbooks/hello-vscode.yml
git commit -m "Add hello-vscode demo playbook"

Add ansible.cfg, inventory and playbooks to Git

bash
git add ansible.cfg inventory/ playbooks/ requirements.yml .gitignore README.md
git status --short
git commit -m "Track Ansible project configuration and playbooks"

Ignore retry files, cache and vault password files

Ensure .gitignore contains *.retry, .cache/, and vault password patterns (see section above), then create empty test artifacts:

bash
touch playbooks/site.retry
install -m 600 /dev/null .vault-pass

Check Git status:

bash
git status --short

Sample output:

Only ignored artifacts should disappear from the untracked list.

Run ansible-playbook from the VS Code terminal

bash
cd ~/ansible-project
ansible-playbook playbooks/hello-vscode.yml --syntax-check
ansible-playbook playbooks/hello-vscode.yml

Run ansible-navigator from the project directory

bash
cd ~/ansible-project
ansible-navigator run playbooks/hello-vscode.yml --mode stdout --ee false

Files to Commit vs Ignore

File / directory Commit? Reason
ansible.cfg Yes Project configuration
inventory/ Usually yes Lab or team inventory
playbooks/ Yes Main automation code
roles/ (custom) Yes Your authored role logic
requirements.yml Yes Reproducible roles and collections
Vault-encrypted vars Usually yes Safe when encrypted and reviewed
Vault password file No Secret used to decrypt Vault
*.retry No Generated run artifact
.cache/ No Tool cache; ansible-lint recreates it
__pycache__/ No Generated Python cache

Common Mistakes

Mistake Fix
Committing vault password files Add .vault-pass, vault.pass, and *.vault-password to .gitignore immediately
Adding a secret to .gitignore after it was committed Use git rm --cached <file> and rotate the secret
Ignoring encrypted Vault vars by mistake Commit encrypted vars when the project needs them; exclude only password files
Running commands outside the project directory Open the repo root in VS Code; cd ~/ansible-project in the integrated terminal
Forgetting to commit requirements.yml Commit it so ansible-galaxy collection install -r requirements.yml reproduces the environment
Editing YAML with tabs Use spaces; enable YAML extension formatting
Committing .retry or .cache/ Add *.retry and .cache/ to .gitignore
Installing roles manually without recording them Add requirements.yml for collections and roles
Depending only on the VS Code UI Learn git status, git diff, git add, git commit in the terminal

Best Practices

  • One repo rootansible.cfg, inventory, and playbooks stay together; matches EX294 and real team layouts.
  • Commit early, commit small — playbook + inventory changes in readable commits beat one giant push.
  • Lint before pushansible-lint playbooks/ catches FQCN and formatting issues cheaply.
  • Never commit secrets — encrypt with Vault; keep password files local and chmod 600.
  • Pin collectionsrequirements.yml with versions avoids "works on my laptop" drift.
  • Editor + CLI — use VS Code for editing and Git graph, terminal for Ansible runs you will automate later.
  • Navigator when helpful — use stdout mode on SSH; use TUI when you want task-by-task browsing (navigator guide).

Summary

A solid Ansible workflow on Rocky Linux is: clone (or init) a Git repo with a standard project tree, open that folder in VS Code, install the Ansible and YAML extensions, edit playbooks with spaces and FQCN modules, run ansible-playbook and ansible-lint from the integrated terminal at the repo root, commit ansible.cfg, inventory, playbooks, and requirements.yml, and keep vault password files, .retry files, and .cache/ out of Git. Add Ansible Navigator when you want its run UI or execution-environment path—after the basics feel natural.


References


Frequently Asked Questions

1. Should I commit ansible.cfg and inventory to Git?

Yes for team and lab projects. ansible.cfg holds project defaults; inventory/ usually holds host names and non-secret variables. Keep vault password files and raw secrets out of the repo.

2. Can I use VS Code without a desktop on the control node?

Yes. Install VS Code on your laptop and use the Remote - SSH extension to open ~/ansible-project on the Rocky Linux control node, or run a desktop session on the VM and open code . locally.

3. What is the difference between the Ansible VS Code extension and Ansible Navigator?

The Red Hat Ansible extension uses ansible-language-server for YAML intelligence, module docs, and editor integration. Ansible Navigator runs and reviews playbook execution, including optional execution-environment containers.

4. Should encrypted Vault files be committed?

Usually yes when the project needs them—encrypted vars are ciphertext, not plain secrets. Never commit the vault password file that decrypts them.

5. Why does ansible-playbook fail when I run it from VS Code?

The integrated terminal cwd must be the project root that contains ansible.cfg. Open the repo folder in VS Code (File → Open Folder) so the terminal starts there.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …