CLOUD
Guides

Server Automation with Ansible: Practical Guide

CLOUD|January 13, 2026|4 min read|552 views
Server Automation with Ansible: Practical Guide

Update 10 servers with one command. Ansible automates repetitive tasks. We cover installation and first 5 practical playbooks.

Why Server Automation?

Managing one server manually is feasible. Managing 5 servers manually is exhausting. Managing 20 servers manually without errors is impossible. This is where automation becomes essential.

Ansible is an open-source automation tool by Red Hat that lets you manage dozens of servers from a single control point without installing agents on the managed nodes. It relies on SSH only — meaning any server you can SSH into, you can manage with Ansible.

Installing Ansible

Install on your local machine (Control Node) — not on the managed servers:

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

# macOS
brew install ansible

# Verify installation
ansible --version

Inventory File

The inventory file defines which servers Ansible manages. Create inventory.ini:

[web_servers]
web1 ansible_host=10.0.1.10 ansible_user=root
web2 ansible_host=10.0.1.11 ansible_user=root

[db_servers]
db1 ansible_host=10.0.1.20 ansible_user=root

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

Test connectivity to all servers:

ansible all -i inventory.ini -m ping

Ad-Hoc Commands

Before writing Playbooks, you can execute commands directly across all servers:

# Update all servers
ansible all -i inventory.ini -m apt -a "upgrade=dist update_cache=yes"

# Check disk space
ansible all -i inventory.ini -m shell -a "df -h /"

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

Writing Your First Playbook

A Playbook is a YAML file describing the desired state of your server. Create setup-web.yml:

---
- name: Setup web servers
 hosts: web_servers
 become: yes

 vars:
 packages:
 - nginx
 - certbot
 - python3-certbot-nginx
 - fail2ban
 - ufw

 tasks:
 - name: Update package cache
 apt:
 update_cache: yes
 cache_valid_time: 3600

 - name: Install required packages
 apt:
 name: "{{ packages }}"
 state: present

 - name: Enable and start nginx
 service:
 name: nginx
 state: started
 enabled: yes

 - name: Allow required ports through UFW
 ufw:
 rule: allow
 port: "{{ item }}"
 proto: tcp
 loop:
 - '22'
 - '80'
 - '443'

 - name: Enable firewall
 ufw:
 state: enabled
 policy: deny

Execute the Playbook:

ansible-playbook -i inventory.ini setup-web.yml

Using Roles for Organization

As your infrastructure grows, organize Playbooks into reusable Roles:

mkdir -p roles/common/tasks roles/common/handlers roles/common/templates
mkdir -p roles/nginx/tasks roles/nginx/handlers roles/nginx/templates

File roles/common/tasks/main.yml:

---
- name: Update system
 apt:
 upgrade: dist
 update_cache: yes

- name: Install essential tools
 apt:
 name:
 - htop
 - curl
 - vim
 - git
 - unzip
 state: present

- name: Set timezone
 timezone:
 name: Asia/Riyadh

Managing Secrets with Ansible Vault

Never store passwords in plain text files. Use Ansible Vault:

# Create encrypted file
ansible-vault create secrets.yml

# Edit encrypted file
ansible-vault edit secrets.yml

# Run playbook with encrypted file
ansible-playbook -i inventory.ini site.yml --ask-vault-pass

Practical Example: Deploy a Laravel Application

---
- name: Deploy Laravel application
 hosts: web_servers
 become: yes
 vars_files:
 - secrets.yml

 tasks:
 - name: Pull latest code
 git:
 repo: "{{ app_repo }}"
 dest: /var/www/app
 version: main
 force: yes

 - name: Install dependencies
 composer:
 command: install
 working_dir: /var/www/app
 no_dev: yes

 - name: Copy environment file
 template:
 src: templates/env.j2
 dest: /var/www/app/.env
 mode: '0600'

 - name: Run migrations
 command: php artisan migrate --force
 args:
 chdir: /var/www/app

 - name: Clear cache
 command: php artisan optimize:clear
 args:
 chdir: /var/www/app

 - name: Set permissions
 file:
 path: /var/www/app/storage
 recurse: yes
 owner: www-data
 group: www-data

Best Practices

Project Structure

ansible-project/
├── inventory/
│ ├── production.ini
│ └── staging.ini
├── roles/
│ ├── common/
│ ├── nginx/
│ ├── php/
│ └── mysql/
├── group_vars/
│ ├── all.yml
│ └── web_servers.yml
├── site.yml
└── ansible.cfg

Golden Rules

  • Always idempotent: A Playbook must produce the same result whether run once or ten times
  • Avoid shell/command when possible: Use specialized modules instead
  • Use tags: To run specific sections of a Playbook
  • Test on staging first: Never experiment directly on production

Integration with CLOUD

CLOUD (cloud.net.sa) servers come ready with full root access and SSH connectivity — which is everything Ansible needs. Start with a server in Riyadh with very low latency and use Ansible to automate everything from initial setup to continuous deployment.

With CLOUD, you can build a fully automated infrastructure without manually logging into each server. Order your VPS from cloud.net.sa and start automating within minutes.


Get Started

Ready to build your project? Configure your cloud server with the specs your app needs, or view plans and pricing.

Share