To try the hands-on steps you will need Ansible installed and a terminal. Everything here is free.
To try the hands-on steps you will need Ansible installed and a terminal. Everything here is free.
Configuration management sets up what runs inside your servers, packages, users, config files, services, automatically and the same way every time. Ansible is the most beginner friendly tool for it. You write a plain YAML file describing the end state you want, and Ansible connects to your servers over SSH and makes it so. No software to install on the servers, and safe to run again and again.
You have twenty servers and need nginx installed and running on all of them, with the same config file, the same user, and the same firewall rule. Doing that by hand means logging into twenty machines and running the same commands twenty times, which is twenty chances to fat-finger a step, skip a server, or set one up slightly differently. Six months later you have twenty servers that were supposed to be identical and quietly are not. Configuration management is how you make many machines truly the same and keep them that way.
Ansible does this from one control machine, usually your laptop or a pipeline, reaching out to every server over plain SSH. Here is the shape before we name the parts.
Part 10 used Terraform to create the servers themselves. Ansible picks up where that leaves off and configures what runs inside them. The two are a classic pair: Terraform builds the empty machines, Ansible turns them into working web servers.
Agentless: just SSH and YAML
Ansible is agentless, and that is a big part of why beginners like it. You do not install anything on the servers you manage. If you can SSH into a machine, Ansible can configure it, because it simply connects over SSH and runs commands the way you would. All you need on your side is Ansible and a list of hosts.
Two files describe your world. An inventory lists the servers, often grouped by role like webservers or databases. A playbook lists the tasks you want carried out on them, written in YAML. Each task calls a module, a small unit that knows how to do one thing correctly, such as installing a package or managing a service. Here are the modules you will reach for constantly.
| Module | What it manages |
|---|---|
apt or dnf | Installed packages |
copy | Put a file onto the server |
template | Render a config file from a template |
service | Start, stop, and enable services |
user | Create and manage user accounts |
A playbook that sets up a web server
Here is a real playbook that installs nginx and makes sure it is running, on every host in the webservers group. Read it as a list of desired outcomes, not commands.
- name: Set up web server
hosts: webservers
become: true
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
- name: Start and enable nginx
ansible.builtin.service:
name: nginx
state: started
enabled: trueThe become: true means run with administrator rights. Each task says what should be true: nginx present, the service started and enabled at boot. Run it and Ansible reports what it did on each host.
$ ansible-playbook -i inventory site.yml
TASK [Install nginx] ***********
changed: [web-01]
TASK [Start and enable nginx] ***********
changed: [web-01]
PLAY RECAP ***********
web-01 : ok=3 changed=2 unreachable=0 failed=0The word changed means Ansible actually did something: it installed nginx and started the service. The recap at the bottom is your report card for the run, one line per host.
Idempotence: why running twice is safe
Run the exact same playbook a second time and something reassuring happens. Nothing changes.
$ ansible-playbook -i inventory site.yml
PLAY RECAP ***********
web-01 : ok=3 changed=0 unreachable=0 failed=0This time changed=0. nginx was already installed and already running, so Ansible checked each desired state, found it already true, and did nothing. This is idempotence, the same property you met with Terraform, and it is what separates configuration management from a plain shell script. A script that runs apt install blindly might error or duplicate work on a second run. Ansible checks first and only acts on the gap, so you can run it as often as you like with no fear.
You run the playbook and one host fails before any task even starts:
fatal: [web-02]: UNREACHABLE! => Failed to connect to the hostvia ssh: Permission denied (publickey)UNREACHABLE means the problem is the SSH connection itself, not your playbook. Ansible never got in the door. The cause is almost always an SSH key that is not set up for that host, a wrong username, or the server being down. Test it directly with
ssh user@web-02 from the same machine. If that fails too, fix the connection first, because Ansible can only configure servers it can log into. This one error teaches the whole model: Ansible is just SSH plus a smart set of commands.Terraform builds, Ansible configures
Beginners often ask whether Terraform and Ansible compete. They do not, they cover different jobs, and understanding the split makes both click. Terraform is best at provisioning: creating the servers, networks, and load balancers that did not exist before. Ansible is best at configuration: taking an existing server and installing and setting up the software on it. A common flow is Terraform first to build a fresh machine, then Ansible to turn it into a configured web server.
You do not always need both. Some teams do all their setup at build time and never run a separate config step. But when you have longer-lived servers to manage, this division of labor is the standard pattern, and naming which tool owns which job is a common interview and on-the-job clarity check.
Handlers and roles keep big playbooks sane
Two ideas keep playbooks from turning into a mess as they grow. The first is a handler, a task that only runs when something else changes. The classic case is restarting a service after its config file is updated. You do not want to restart nginx on every run, only when the config actually changed, so the config task notifies a handler, and the handler restarts nginx just once, at the end, only if a change happened. This keeps runs both correct and calm, with no needless restarts.
The second idea is a role, a way to package a whole set of related tasks, files, and templates into a reusable bundle. Instead of one giant playbook, you build a role called webserver and another called database, and your playbook simply applies the right roles to the right groups. It is the same write-once instinct you saw with Terraform modules, applied to configuration. You do not need roles on day one, but the moment a playbook grows past a screen or two, they are how you keep it readable. To place Ansible next to the tool from the last part, here is the split one more time, side by side.
| Job | Terraform | Ansible |
|---|---|---|
| Create servers and networks | Yes, its main job | Not really |
| Install and configure software | Not really | Yes, its main job |
| How it connects | Cloud and platform APIs | SSH to the servers |
| Typical order | First, build the machine | Second, set it up |
How containers changed configuration management
Here is a take some older guides will not tell you. In a world built on containers, the role of configuration management has shrunk. When you package an app in a Docker image, the configuration is baked into the image itself, and you replace the whole container to change it rather than logging in to reconfigure a running server. In that model there are no long-lived servers to keep in shape, so a tool like Ansible has less to do. This is real, and it means you should not assume every modern stack leans heavily on Ansible.
That said, Ansible is far from dead, and it is still worth learning. Plenty of real systems run on long-lived virtual machines rather than containers, especially in enterprises and on-premise setups, and those need exactly this kind of management. Ansible is also excellent for one-off orchestration, like rolling a change across a fleet or setting up the machines that host your container platform in the first place. Learn it, understand where it shines, and be honest that a pure-container shop may use it lightly or not at all.
What does idempotent mean, and why does Ansible care about it? Answer: an idempotent action produces the same result whether you run it once or many times. Ansible checks the current state of each thing before acting and only makes a change if reality does not already match the desired state, so a playbook is safe to run repeatedly. Contrast that with a naive shell script that blindly repeats commands and can fail or duplicate work on a second run. Naming that difference shows you understand why declarative tools exist, which is the heart of modern operations.
If your team uses Ansible, you will run playbooks and read their recaps far more often than you write new ones. Being able to look at
ok=5 changed=1 failed=0 and know exactly what happened, and to spot that an UNREACHABLE means fix the SSH connection first, makes you productive without deep expertise. The instinct that a second run showing changed=0 is good news, not a broken run, is the small kind of understanding that marks someone who gets configuration management rather than just copying commands.Free, about twenty minutes. Install Ansible, then use localhost as your target so you need no other machine. Write a tiny playbook that creates a file with the copy module or installs a small package, and run it with
ansible-playbook. Watch the recap say changed on the first run. Run it again and watch it say changed=0. How to check you did it right: the first run reports a change and the file or package appears, and the second run reports no change while the result stays in place. You have just seen idempotence for yourself.Before you run a playbook against real servers, run it with
--check. This is a dry run: Ansible reports what it would change without changing anything, exactly like Terraform is plan step. You see which tasks would show changed and on which hosts, so a surprise never lands on production. Pair it with -v for more detail when a task behaves oddly, and read the recap line for every host, not just the first. The habit of always dry running against production, and reading the recap host by host, is the difference between a calm operator and one who learns caution the hard way after a bad run.Ansible questions beginners ask
How is a playbook different from a bash script?
A bash script says do these steps. A playbook says make these things true, and Ansible works out whether each step is even needed. That makes playbooks safe to rerun and easier to read as a description of the end state, where a long script becomes a tangle of checks and conditionals.
Do I need to install anything on the servers?
No, that is the point of agentless. The managed servers need only SSH access and Python, which almost every Linux server already has. Everything else lives on your control machine, which keeps the servers clean and lowers what can go wrong.
What is an inventory?
The list of hosts Ansible manages, usually grouped by role. A playbook targets a group like webservers, and Ansible runs the tasks on every host in it. The inventory is how one playbook scales from one server to a hundred without changing a line.
Is Ansible the only configuration tool?
No. Chef, Puppet, and SaltStack do similar jobs, but Ansible is the friendliest to start with because it is agentless and uses plain YAML. Learn the ideas here, idempotence, desired state, inventories, and they carry to any of them.
You have now seen how servers get built and configured as code. That closes the build and provision side of DevOps. Next up is Part 12 on monitoring and observability, where you learn to watch what all of this does once it is running in production.
New here? Start with Part 10 on Terraform, which pairs with Ansible, and Part 4 on the Linux command line that Ansible drives. The Python for Beginners series helps, since Ansible runs on Python.
References
Ansible: Getting started
Ansible: Intro to playbooks
Ansible builtin modules


DrJha