Ansible Automation on Linux: From Install to First Playbook

If you manage more than a handful of Linux servers, you have probably hit the wall where SSH and bash scripts stop scaling. You patch one server, forget another. A config change goes on three nodes but misses a fourth. Ansible automation on Linux solves this by turning infrastructure tasks into repeatable YAML files that run across every server at once. No agents to install on managed nodes. No master server to maintain. Just SSH and a playbook. This guide takes you from a fresh install to your first real automation task.

Ansible automation Linux server configuration management playbook
Ansible manages hundreds of servers from a single control node over SSH, with no agent software needed on any managed host.

How Ansible Works

Ansible runs from a control node, any Linux machine with Python and SSH access to your servers. You write tasks in YAML files called playbooks. When you run a playbook, Ansible connects to each target over SSH, runs a small Python script, then removes it. Nothing stays on the managed node after the run finishes.

This agentless design is one of Ansible’s biggest practical advantages. You do not need to pre-install anything on new servers before managing them. As long as SSH works and Python 3 is available, which it is on every modern Linux distribution, Ansible can manage it.

Four concepts cover most of what you need to start: inventory (the list of servers), playbooks (YAML files that define what to do), tasks (individual steps inside a playbook), and modules (built-in functions like apt, service, and copy). The full module list is on the Ansible module index.

Install Ansible on Your Control Node

Install ansible-core using pip for the most current version:

# Ubuntu / Debian
apt install python3-pip -y
pip3 install ansible-core

# RHEL / AlmaLinux
dnf install python3-pip -y
pip3 install ansible-core

# Verify
ansible --version

You should see ansible [core 2.20.x] in the output. The pip version stays more current than the package manager version, so pip is the better choice for most setups. If you prefer package-managed installs:

apt install ansible -y         # Ubuntu/Debian
dnf install ansible-core -y    # RHEL/AlmaLinux

Set Up SSH Key Authentication

Ansible automation Linux SSH key setup inventory hosts file
Ansible uses the same SSH authentication as your terminal. Sort this out before writing a single playbook.

Ansible connects over SSH. Before running any playbook, you need passwordless SSH access from your control node to every managed host. Generate a key if you do not have one:

ssh-keygen -t ed25519 -C "ansible-control"

Copy your public key to each managed server:

ssh-copy-id user@server1
ssh-copy-id user@server2

Test it works without a password prompt:

ssh user@server1 "echo connected"

The most common reason first playbooks fail is SSH authentication not working. Sort this out manually first, and you avoid a confusing UNREACHABLE error when Ansible runs.

Create Your Inventory File

The inventory file tells Ansible which servers to manage. Create a project directory and add an inventory file:

mkdir ~/ansible-project && cd ~/ansible-project
nano inventory.ini

Group servers by role for easier targeting:

[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu
web2 ansible_host=192.168.1.11 ansible_user=ubuntu

[dbservers]
db1 ansible_host=192.168.1.20 ansible_user=ubuntu

[all:vars]
ansible_python_interpreter=/usr/bin/python3

Test that Ansible reaches all your hosts:

ansible all -i inventory.ini -m ping

Every host should return a green pong. If any show UNREACHABLE, fix the SSH access for that host before continuing.

Write Your First Playbook

A playbook is a YAML file that defines what Ansible should do. This one installs and starts Nginx on all web servers:

---
- name: Configure web servers
  hosts: webservers
  become: true

  tasks:
    - name: Update apt cache
      apt:
        update_cache: true
      when: ansible_os_family == "Debian"

    - name: Install Nginx
      package:
        name: nginx
        state: present

    - name: Start and enable Nginx
      service:
        name: nginx
        state: started
        enabled: true

    - name: Deploy index page
      copy:
        content: "<h1>Managed by Ansible</h1>"
        dest: /var/www/html/index.html
        mode: '0644'

Run it with:

ansible-playbook -i inventory.ini webservers.yml

Tasks that make a change show as changed (yellow). Tasks that find the system already in the correct state show as ok (green). Nothing shows as an error unless something actually failed.

Understand Idempotency

Idempotency is the most important concept in Ansible. It means running the same playbook multiple times produces the same result each time. The second run does not reinstall Nginx if it is already installed. It does not overwrite a file if the content already matches.

This is what makes Ansible automation on Linux reliable in production. Run a playbook against your servers every night as a drift check. If someone manually changed a config, Ansible corrects it on the next run. Your servers stay in the state your playbook defines.

Useful Ansible Modules

Ansible automation Linux playbook modules tasks YAML server management
Ansible has over 3,000 built-in modules. These are the ones that appear in almost every real-world playbook.

These modules cover the vast majority of real-world server management tasks:

Module What It Does Common Use
apt / dnf Manage packages Install, remove, update software
service Manage systemd services Start, stop, enable, disable
copy Copy files to hosts Deploy static config files
template Jinja2 templates Config files with variables
user Manage user accounts Create users, set SSH keys
file Manage files and dirs Permissions, create paths
lineinfile Edit lines in files Change one setting in a config
command Run shell commands One-offs not covered by modules

Always prefer a dedicated module over command or shell when one exists. Dedicated modules handle idempotency correctly. Raw shell commands run every time regardless of current state.

Add Variables and Use Templates

Hard-coding values limits reuse. Variables make playbooks flexible across different environments:

---
- name: Configure app server
  hosts: webservers
  become: true
  vars:
    app_port: 3000
    app_user: deploy

  tasks:
    - name: Create app user
      user:
        name: "{{ app_user }}"
        state: present

    - name: Open app port in firewall
      ufw:
        rule: allow
        port: "{{ app_port }}"
        proto: tcp

For config files with dynamic values, use the template module with a Jinja2 template. The Ansible Galaxy library also has thousands of pre-built roles covering common tasks like setting up databases, configuring firewalls, and deploying web servers.

Run Ad-Hoc Commands

For quick one-off tasks, Ansible runs commands directly without a playbook:

# Check disk space on all servers
ansible all -i inventory.ini -m command -a "df -h" --become

# Restart Nginx on web servers only
ansible webservers -i inventory.ini -m service -a "name=nginx state=restarted" --become

# Check kernel version across the fleet
ansible all -i inventory.ini -m command -a "uname -r"

Ad-hoc commands use the same inventory and SSH config as playbooks. They are fast for gathering information or running a quick fix without writing YAML.

Combine Ansible with Server Hardening

One of the best uses of Ansible is applying a consistent security baseline to every server you provision. Instead of running a hardening checklist manually each time, write a hardening playbook once and run it at build time. It sets SSH config, installs fail2ban, configures firewall rules, and applies sysctl settings in one shot. See our Linux server hardening checklist for the individual steps, then convert each section into an Ansible task. Also, after hardening a new server, you can deploy an Nginx reverse proxy with a single playbook run. Our guide on setting up Nginx reverse proxy on Linux covers the manual steps that translate directly into tasks.

Conclusion

Getting started with Ansible automation on Linux takes about 30 minutes. Install ansible-core, set up SSH key access, write an inventory file, and run a playbook. After that first successful run, the use cases multiply fast. Package installs, user management, config deployment, security baselines. Ansible handles all of it with the same pattern: write the desired state in YAML, run the playbook, trust the output. Start with two or three servers and one simple playbook. The rest follows naturally from there.

}