Guide to using Claude Code CLI to generate, refactor, lint, and run an Ansible playbook that installs and configures Apache httpd on RHEL hosts.
In this lesson you will use the Claude Code For Beginners CLI to generate and refine an Ansible playbook that installs and configures the Apache (httpd) web server on RHEL-based hosts. The walkthrough covers setting up a control-node workspace, generating a baseline playbook with Claude Code, refactoring to best practices (FQCNs, templates, lineinfile, handlers), validating, and running the playbook.
Overview — workflow
Create a working directory and inventory
Configure ansible.cfg
Use Claude Code to generate site.yml (the playbook)
Validate and refactor the playbook (use FQCNs, add template, lineinfile, handlers)
Run ansible-lint / validate
Execute the playbook and verify the result
For quick reference, here’s the workflow in a compact table:
Step
Action
Why
1
Create workspace + inventory
Tell Ansible which hosts to manage
2
Configure ansible.cfg
Ensure consistent behaviour and privilege escalation
3
Generate site.yml via Claude Code
Quickly scaffold a working playbook
4
Refactor (FQCNs, template, lineinfile)
Improve clarity, maintainability, and idempotence
5
Lint/validate
Catch issues early with ansible-lint
6
Run playbook and verify
Confirm the web server is configured correctly
Preparation — create the control-node workspace
Run these commands in your Claude Code workspace to create a working directory and files:
Copy
student@control:~/claude$ pwd/home/student/claudestudent@control:~/claude$ vim inventorystudent@control:~/claude$ vim ansible.cfgstudent@control:~/claude$ claude
Generate an initial playbook with Claude Code
Start an interactive Claude Code session and ask it to create a playbook named site.yml that installs httpd on hosts in the webservers group (RHEL-based systems). Example CLI snippet:
Copy
student@control:~/claude$ claudeClaude Code v2.0.37Welcome back andrei!/home/student/claude> Create an ansible playbook file called site.yml which installs httpd on the group of hosts called webservers which are RHEL-based systems.
Claude Code will typically generate a simple playbook like this. Open site.yml in your editor to inspect it.Initial generated site.yml
Copy
---- name: Install and configure httpd on webservers hosts: webservers become: yes tasks: - name: Install httpd package yum: name: httpd state: present - name: Start and enable httpd service service: name: httpd state: started enabled: yes
Refactor to use Fully Qualified Collection Names (FQCNs)
Best practice: use FQCNs such as ansible.builtin.yum and ansible.builtin.service to avoid ambiguity and ensure the intended module is executed. Ask Claude Code to refactor the playbook to FQCNs or update it yourself.site.yml with FQCNs
Copy
---- name: Install and configure httpd on webservers hosts: webservers become: yes tasks: - name: Install httpd package ansible.builtin.yum: name: httpd state: present - name: Start and enable httpd service ansible.builtin.service: name: httpd state: started enabled: yes
Add a Jinja2 template to serve host facts
Create a template that renders host-specific facts (hostname and fqdn) to /var/www/html/index.html. Example template (index.html.j2):index.html.j2
Copy
<!DOCTYPE html><html><head> <title>Welcome</title></head><body> <h1>Welcome to {{ ansible_hostname }}</h1> <p>This page is served from host: {{ ansible_fqdn }}</p></body></html>
Deploy the template and use lineinfile for attribution
Rather than embedding the attribution directly into the template, demonstrate combining modules: deploy the template using ansible.builtin.template, then add an attribution line using ansible.builtin.lineinfile. Notify a handler to reload httpd when the file changes.Tasks to add
Copy
- name: Deploy index.html from template ansible.builtin.template: src: index.html.j2 dest: /var/www/html/index.html owner: root group: root mode: '0644' notify: Reload httpd- name: Add attribution line to index.html ansible.builtin.lineinfile: path: /var/www/html/index.html line: "This was created by ansible and claude" insertbefore: '</body>' notify: Reload httpd
PLAY [Install and configure httpd on webservers] ********************************TASK [Gathering Facts] *********************************************************ok: [servera]TASK [Install httpd package] ***************************************************changed: [servera]TASK [Start and enable httpd service] ******************************************changed: [servera]TASK [Deploy index.html from template] *****************************************changed: [servera]TASK [Add attribution line to index.html] **************************************changed: [servera]RUNNING HANDLER [Reload httpd] *************************************************changed: [servera]
Verify on the managed host
Confirm the web page is served and contains the expected facts and attribution.
Copy
student@servera:~$ curl localhost:80<!DOCTYPE html><html><head> <title>Welcome</title></head><body> <h1>Welcome to servera</h1> <p>This page is served from host: servera</p>This was created by ansible and claude</body></html>student@servera:~$
Wrapping up
You have used Claude Code For Beginners to scaffold an Ansible playbook, refactored it to follow best practices (FQCNs, templates, handlers), and executed it against a managed RHEL-based host. This pattern—generate, inspect, refactor, and validate—helps you move quickly while keeping playbooks maintainable and predictable.Links and references