Ansible automates server configuration over plain SSH. There’s no agent to install on servers: you describe the desired state — packages installed, files in place, services running — and Ansible connects, checks and changes only what’s needed. It’s the easiest way to manage more than one or two servers consistently.

How Ansible works

  • You run Ansible on a control node (your laptop, a CI runner or an admin VPS).
  • It connects over SSH to managed nodes listed in an inventory.
  • It runs modules (small programs for tasks like apt, copy, service) on the targets, which only need Python and SSH.

1. Install Ansible on the control node

The recommended way is with pipx, which gives you a current version:

sudo apt install -y pipx
pipx install --include-deps ansible
pipx ensurepath
ansible --version

Alternatives: sudo apt install ansible (Ubuntu’s version, sometimes older), the Ansible PPA, or brew install ansible on macOS. Windows users run Ansible inside WSL.

2. SSH access to your servers

Ansible uses your normal SSH setup. Make sure key-based login works for each server:

ssh-copy-id [email protected]
ssh [email protected] 'python3 --version'

The remote user should have sudo rights for administrative tasks. See SSH keys.

3. Create an inventory

A project directory with inventory.ini:

[web]
web1 ansible_host=203.0.113.10
web2 ansible_host=203.0.113.11

[db]
db1 ansible_host=203.0.113.20

[all:vars]
ansible_user=deploy

And ansible.cfg next to it:

[defaults]
inventory = inventory.ini
host_key_checking = True
interpreter_python = auto_silent

Inventories can also be YAML, and can be generated dynamically from cloud APIs. See Ansible inventory.

4. Ad-hoc commands

Test connectivity:

ansible all -m ping
web1 | SUCCESS => { "changed": false, "ping": "pong" }

Run commands across groups:

ansible web -m command -a "uptime"
ansible all -m shell -a "df -h / | tail -1"
ansible db -m setup -a "filter=ansible_distribution*"     # gather facts

Administrative tasks need become (sudo):

ansible all -b -m apt -a "update_cache=yes upgrade=dist"
ansible web -b -m apt -a "name=nginx state=present"
ansible web -b -m service -a "name=nginx state=restarted"
ansible all -b -K -m apt -a "name=htop state=present"     # -K asks for the sudo password

5. Idempotency: the key idea

Run the nginx install twice:

ansible web -b -m apt -a "name=nginx state=present"

The first run reports changed: true; the second changed: false — Nginx is already there, so nothing is done. Modules describe state, not steps. That’s why Ansible runs are safe to repeat, and why command/shell modules (which can’t know whether they’re needed) should be a last resort.

6. Useful modules

Module Purpose
apt / dnf / package Install, update, remove packages
service / systemd Start, stop, enable services
copy / template Put files (with Jinja2 templating) on servers
lineinfile / blockinfile Edit lines in config files
user / group / authorized_key Manage accounts and SSH keys
file Directories, permissions, symlinks
ufw / firewalld Firewall rules
git Check out repositories
docker_container / docker_compose_v2 Manage containers (community.docker collection)

Docs: ansible-doc apt.

7. Next: playbooks

Ad-hoc commands are great for quick tasks. For repeatable configuration, write playbooks — YAML files listing tasks per host group — and keep them in Git. See the Ansible playbook tutorial.

Tips

  • Use --check (dry run) and --diff to preview changes.
  • Limit to one host: --limit web1.
  • Increase parallelism for many servers: -f 20 (forks).
  • Keep secrets in Ansible Vault — see Ansible Vault.

Ansible shines when you manage several VPS servers — for example web servers in USA and Hong Kong that must stay identical.

  • Ansible
  • Automation
  • DevOps