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.
