🎁 New User? Get 20% off your first purchase with code NEWUSER20 Register Now →
Menu

Categories

How to Set Up Ansible for Multi-Server Management: A Complete Step-by-Step Guide

How to Set Up Ansible for Multi-Server Management: A Complete Step-by-Step Guide

Managing multiple servers manually is time-consuming, error-prone, and simply does not scale. Ansible solves this problem by letting you define your infrastructure as code and apply configurations across hundreds of servers with a single command. This step-by-step guide will take you from installation to managing a multi-server environment.

Prerequisites

Before starting, ensure you have:

  • A control node running Linux (Ubuntu 22.04+ or AlmaLinux 9+ recommended)
  • At least 2-3 target servers (can be VMs for practice)
  • SSH access to all target servers
  • Python 3.9+ on all systems
  • Root or sudo access on the control node

Step 1: Install Ansible on the Control Node

Install Ansible using your distribution's package manager or pip:

# Ubuntu/Debian
sudo apt update
sudo apt install -y ansible

# AlmaLinux/RHEL
sudo dnf install -y ansible-core

# Via pip (any distribution)
pip3 install ansible

# Verify installation
ansible --version

Step 2: Set Up SSH Key Authentication

Ansible communicates with managed nodes over SSH. Set up key-based authentication for passwordless access:

# Generate SSH key pair (if you don't have one)
ssh-keygen -t ed25519 -C "ansible-controller"

# Copy public key to each managed node
ssh-copy-id user@webserver1.example.com
ssh-copy-id user@webserver2.example.com
ssh-copy-id user@dbserver1.example.com

# Test connectivity
ssh user@webserver1.example.com "hostname"

Step 3: Create Your Inventory File

The inventory defines your managed servers and how they are organized:

# /etc/ansible/hosts or ./inventory/hosts.ini
[webservers]
web1 ansible_host=192.168.1.10 ansible_user=admin
web2 ansible_host=192.168.1.11 ansible_user=admin

[dbservers]
db1 ansible_host=192.168.1.20 ansible_user=admin
db2 ansible_host=192.168.1.21 ansible_user=admin

[monitoring]
monitor1 ansible_host=192.168.1.30 ansible_user=admin

[production:children]
webservers
dbservers
monitoring

[production:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_become=yes

Step 4: Configure ansible.cfg

Create a project-level configuration file:

# ansible.cfg in your project root
[defaults]
inventory = ./inventory/hosts.ini
remote_user = admin
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml

[privilege_escalation]
become = True
become_method = sudo
become_ask_pass = False

Step 5: Test Connectivity

# Ping all hosts
ansible all -m ping

# Ping specific group
ansible webservers -m ping

# Gather facts from all hosts
ansible all -m setup --tree /tmp/facts

Step 6: Create Your First Playbook

Create a playbook that configures all servers with common settings:

# playbooks/common.yml
---
- name: Common Server Configuration
  hosts: all
  become: yes

  vars:
    common_packages:
      - vim
      - htop
      - curl
      - wget
      - unzip
      - git
      - fail2ban
    timezone: "Europe/Amsterdam"
    ntp_servers:
      - 0.pool.ntp.org
      - 1.pool.ntp.org

  tasks:
    - name: Update package cache
      apt:
        update_cache: yes
        cache_valid_time: 3600
      when: ansible_os_family == "Debian"

    - name: Install common packages
      package:
        name: "{{ common_packages }}"
        state: present

    - name: Set timezone
      timezone:
        name: "{{ timezone }}"

    - name: Configure NTP
      template:
        src: templates/ntp.conf.j2
        dest: /etc/ntp.conf
      notify: Restart NTP

    - name: Enable and start fail2ban
      systemd:
        name: fail2ban
        state: started
        enabled: yes

    - name: Set up automatic security updates
      apt:
        name: unattended-upgrades
        state: present
      when: ansible_os_family == "Debian"

  handlers:
    - name: Restart NTP
      systemd:
        name: ntp
        state: restarted

Step 7: Create Role-Specific Playbooks

# playbooks/webservers.yml
---
- name: Configure Web Servers
  hosts: webservers
  become: yes

  tasks:
    - name: Install NGINX
      apt:
        name: nginx
        state: present

    - name: Deploy NGINX config
      template:
        src: templates/nginx-site.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Reload NGINX

    - name: Configure firewall for HTTP/HTTPS
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - "80"
        - "443"

  handlers:
    - name: Reload NGINX
      systemd:
        name: nginx
        state: reloaded

Step 8: Run Your Playbooks

# Run common configuration on all servers
ansible-playbook playbooks/common.yml

# Run with verbose output for debugging
ansible-playbook playbooks/common.yml -vv

# Dry run (check mode)
ansible-playbook playbooks/common.yml --check --diff

# Limit to specific hosts
ansible-playbook playbooks/common.yml --limit web1

# Run with tags
ansible-playbook playbooks/common.yml --tags "packages,firewall"

Best Practices for Multi-Server Management

  • Use roles — Organize related tasks into reusable roles
  • Version control everything — Keep playbooks, inventory, and templates in Git
  • Use Ansible Vault — Encrypt sensitive variables like passwords and API keys
  • Test in staging first — Always run playbooks against non-production environments first
  • Use check mode — Preview changes with --check --diff before applying

With this setup, you can manage your entire server fleet from a single control node. As your infrastructure grows, Ansible scales with you.

Further Reading

Share this article:
Mikkel Sorensen
About the Author

Mikkel Sorensen

UX/UI Design, Java Development, User-Centered Application Design, Technical Documentation

Mikkel Sørensen is a UX/UI-focused software developer with a strong background in Java-based application development.

He works at the intersection of user experience design and software engineering, creating applications that are both technically robust and user-centered. His experience includes interface design, inter...

UX Design UI Design Java Applications User Experience Engineering Accessibility Basics

Stay Updated

Subscribe to our newsletter for the latest tutorials, tips, and exclusive offers.