Install Ansible, build a small inventory, validate connectivity with an ad-hoc ping, and run a playbook to configure web hosts. Prove idempotency by re-running the playbook and confirming no unnecessary changes occur.
You need to deploy Ansible to automate routine server tasks. Your starting point is a small fleet: one web host and one database host, both reachable on a private network.
The goal is repeatability. Define targets, validate connectivity, apply a change via playbook, and confirm re-runs do not introduce unnecessary changes.
web and db groups.ping module run.nginx on web hosts.setup module.nginx from the web group.ping, setup).
become and one-off escalation with -b.
package for installs/removals and service for runtime state.
sudo dnf install ansible -y
Install from the distro repositories so you get predictable paths and a supported runtime. This reduces “works on my laptop” drift when you move between environments.
ansible --version
Confirm the reported config file location and
Python runtime. If behavior differs between systems, this is
your first sanity check.
# Expected patterns:
# ansible [core ...]
# config file = /etc/ansible/ansible.cfg (or similar)
nano ~/inventory
# OR
vim ~/inventory
[web]
192.168.122.10
[db]
192.168.122.11
Keep this minimal for day-one ops. In a real environment you
would add connection variables (user, key, port) or define
defaults in ansible.cfg.
ansible all -i ~/inventory -m ping
This checks whether Ansible can reach the hosts and execute a module. Do not move to playbooks until this returns clean success on your targets.
# Expected patterns:
# 192.168.122.10 | SUCCESS => {"changed": false, "ping": "pong"}
nano install_nginx.yml
# OR
vim install_nginx.yml
- name: Install nginx
hosts: web
become: yes
tasks:
- name: Install nginx
package:
name: nginx
state: present
This is a clean starter because package abstracts
the underlying package manager. You declare the desired
state and let the module handle the mechanics.
ansible-playbook -i ~/inventory install_nginx.yml
The first run should report changed for tasks
that apply new state. That is expected when the package is
not present yet.
nano install_nginx.yml
# OR
vim install_nginx.yml
- name: Install nginx
hosts: web
become: yes
tasks:
- name: Install nginx
package:
name: nginx
state: present
- name: Ensure nginx is running
service:
name: nginx
state: started
enabled: yes
This is the operational baseline: install the package, ensure the service is started, and ensure it persists across reboot.
ansible-playbook -i ~/inventory install_nginx.yml
A clean re-run should show mostly ok. You only
want changed when something actually needed
correction.
ansible all -i ~/inventory -m setup
Facts output is large. In real playbooks, you use facts to branch logic (OS family, interfaces, storage, and system metadata) without hardcoding assumptions.
ansible web -i ~/inventory -m package -a "name=nginx state=absent" -b
This resets the environment for repetition. Treat cleanup as part of the workflow, not an afterthought.
If ad-hoc ping fails, fix connectivity first. Confirm DNS/IP reachability, SSH access, and privilege escalation behavior before running playbooks.
Confirm you are pointing to the right inventory file with
-i
and that the group names match exactly. A typo in
hosts: web
will silently target nothing.
Ensure SSH authentication is set up and that escalation works
for the remote user. If become requires a password,
you may need to configure sudo policy or supply the correct
authentication method.
Validate the unit and logs on the target host. Common causes include port conflicts, missing dependencies, or SELinux and firewall policy.
This lab leaves only package and service state changes on the
web hosts. Cleanup is removing nginx and confirming
the playbook converges cleanly afterward.
ansible web -i ~/inventory -m package -a "name=nginx state=absent" -b
ansible web -i ~/inventory -m service -a "name=nginx state=stopped" -b
The package is absent on the web group and a re-run of the playbook reports predictable results without repeated changes.
dnf install ansible -y
: Installs Ansible from distro repositories.
-y
: Automatically answers yes to prompts.
ansible --version
: Shows Ansible version, config file path, and runtime details.
nano <file>
: Opens a file for editing.
vim <file>
: Opens a file for editing.
ansible all -i <inventory> -m ping
: Validates Ansible connectivity to target hosts.
-i <inventory>
: Specifies the inventory file to use.
-m ping
: Runs the ping module (connectivity check).
ansible-playbook -i <inventory> <playbook>
: Runs a playbook against targets defined in the inventory.
-i <inventory>
: Specifies the inventory file to use.
ansible all -i <inventory> -m setup
: Gathers system facts from target hosts.
-m setup
: Runs the setup module (facts gathering).
ansible <group> -i <inventory> -m package -a "<args>" -b
: Manages packages on a target group using the package module.
-a "<args>"
: Supplies module arguments (for example name=nginx state=present).
-b
: Enables privilege escalation (become).
ansible <group> -i <inventory> -m service -a "<args>" -b
: Manages service state on a target group using the service module.
-a "<args>"
: Supplies module arguments (for example name=nginx state=started enabled=yes).
-b
: Enables privilege escalation (become).