What You'll Learn
How to automate server configuration with Ansible Playbooks — inventory, tasks, handlers, variables, roles, and a complete Nginx setup example.
Why Ansible?
Ansible is a powerful configuration management and IT automation tool. Unlike Chef or Puppet, it is agentless. It uses standard SSH to connect to your servers, meaning you don't need to install any custom software on the target machines — just Python.
The Inventory File
The inventory tells Ansible which servers to manage. It can be a static INI file or dynamic (pulling from AWS/GCP).
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.com
db2.example.com
[production:children]
webservers
databases
[production:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/prod_key.pem
Writing a Playbook
Playbooks are YAML files that describe the desired state of your systems. They contain one or more "Plays", which map groups of hosts to tasks.
---
- name: Setup Web Servers
hosts: webservers
become: yes # Run commands as sudo/root
vars:
app_port: 8080
domain: "example.com"
tasks:
- name: Ensure apt cache is up to date
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install Nginx
apt:
name: nginx
state: present
- name: Create app directory
file:
path: /var/www/myapp
state: directory
owner: www-data
group: www-data
mode: '0755'
- name: Deploy custom index.html template
template:
src: templates/index.html.j2
dest: /var/www/myapp/index.html
notify: restart nginx # Triggers handler if file changes!
- name: Configure Nginx virtual host
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/myapp.conf
notify: restart nginx
- name: Enable Nginx site (create symlink)
file:
src: /etc/nginx/sites-available/myapp.conf
dest: /etc/nginx/sites-enabled/myapp.conf
state: link
notify: restart nginx
- name: Ensure Nginx is running and enabled on boot
service:
name: nginx
state: started
enabled: yes
# Handlers only run once at the end of the play,
# and only if notified by a changed task
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Running Commands
# Ad-hoc command: ping all servers
ansible all -i inventory.ini -m ping
# Ad-hoc command: check disk space
ansible webservers -i inventory.ini -m command -a "df -h"
# Run a playbook
ansible-playbook -i inventory.ini setup-webserver.yml
# Dry run (check mode) - show what would change without doing it
ansible-playbook -i inventory.ini setup-webserver.yml --check
# Syntax check
ansible-playbook setup-webserver.yml --syntax-check
Ansible Roles (For Larger Projects)
As your playbooks grow, you should split them into Roles. A role bundles variables, tasks, files, and templates into a standardized directory structure.
# Create a skeleton role
ansible-galaxy init nginx_role
# Using a role in a playbook:
- name: Setup Web Server
hosts: webservers
roles:
- common_security
- nginx_role
- app_deploy