
September 09, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
You maintain a handful of Ubuntu servers running Laravel, WordPress, or WooCommerce. Every new PHP version or SSL renewal still means SSH, copy-paste, and crossed fingers. Ansible Playbooks: A Practical Guide shows how to replace that manual work with repeatable YAML automation. Ansible is agentless, uses SSH, and fits teams already doing Linux system administration in Nepal or managing shared EC2 boxes. This page walks from your first playbook to production patterns I use alongside GitLab CI and Deployer.
ansible-playbook against an inventory over SSH. Ansible is idempotent: re-running the same playbook fixes drift without breaking what already matches.What Is Ansible Playbooks: A Practical Guide for Server Automation?
An Ansible playbook is a ordered list of plays. Each play targets a host group and runs tasks through modules. You do not install an agent on servers. The control machine—your laptop or a CI runner—connects over SSH and pushes changes.
That model matches how many small teams operate. You already have root or sudo access on production. You already use Git for application code. Playbooks extend Git to infrastructure: versioned, reviewable, repeatable.
Core pieces you will use daily:
- Inventory — lists hosts and groups (
web,db,staging). - Playbook — YAML file defining plays and tasks.
- Modules — atomic units like
apt,copy,template,service. - Roles — reusable task bundles; see Ansible roles and Galaxy for reusable automation.
- Vault — encrypts secrets inside the repo; covered in encrypting secrets in playbooks with Ansible Vault.
Official docs describe playbooks as the core configuration method in Ansible. Read the Ansible playbook introduction when you need module-level detail beyond this guide.
Where Ansible fits in a Laravel shop: Terraform or your cloud panel creates the VM. Ansible configures it—PHP 8.4, Composer 2.10, Redis 8.10, UFW, fail2ban. Deployer or GitLab CI deploys application code after the box is ready. That split is explained well in Terraform vs Ansible: provisioning vs configuration management.
How Do You Write Your First Ansible Playbook?
Install Ansible on Ubuntu 24.04 from the control machine:
sudo apt update
sudo apt install -y ansible
ansible --version Create a project layout:
mkdir -p ~/ansible-laravel/{inventory,playbooks,roles,group_vars}
cd ~/ansible-laravel Define inventory
File: inventory/production.ini
[web]
web1 ansible_host=203.0.113.10 ansible_user=deploy
[web:vars]
ansible_python_interpreter=/usr/bin/python3
php_version=8.4
app_user=deploy Use IP addresses or DNS names. Match the SSH user you already use for automating server setup with Ansible playbooks.
Write a minimal playbook
File: playbooks/base.yml
---
- name: Base Ubuntu hardening and packages
hosts: web
become: true
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Install base packages
ansible.builtin.apt:
name:
- curl
- git
- ufw
- fail2ban
state: present
- name: Allow OpenSSH through UFW
community.general.ufw:
rule: allow
name: OpenSSH
- name: Enable UFW
community.general.ufw:
state: enabled Run it
ansible-playbook -i inventory/production.ini playbooks/base.yml --check
ansible-playbook -i inventory/production.ini playbooks/base.yml Always dry-run with --check first on unfamiliar hosts. Add -l web1 to limit scope during testing.
How Do You Structure Ansible Playbooks for Production PHP and Laravel Servers?
A single 400-line playbook becomes unmaintainable fast. Split by concern. This mirrors how I organise automation for sites like Notary Kathmandu and other sister properties on shared infrastructure.
Recommended directory layout
ansible-laravel/
├── ansible.cfg
├── inventory/
│ ├── production.ini
│ └── staging.ini
├── group_vars/
│ ├── all.yml
│ └── web.yml
├── playbooks/
│ ├── site.yml
│ ├── web.yml
│ └── db.yml
└── roles/
├── common/
├── php_fpm/
├── nginx/
└── deploy_user/ Entry playbook site.yml imports others:
---
- import_playbook: web.yml
- import_playbook: db.yml Variables in group_vars
File: group_vars/web.yml
php_packages:
- "php{{ php_version }}-fpm"
- "php{{ php_version }}-mysql"
- "php{{ php_version }}-redis"
- "php{{ php_version }}-xml"
- "php{{ php_version }}-mbstring"
- "php{{ php_version }}-curl"
nginx_server_name: example.com
laravel_path: /var/www/example/current Validate variable files with the JSON formatter tool when converting from other formats. YAML indentation errors are the top cause of playbook failures.
Template a config file
Roles/nginx/templates/site.conf.j2:
server {
listen 80;
server_name {{ nginx_server_name }};
root {{ laravel_path }}/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php{{ php_version }}-fpm.sock;
}
} Task using the template module:
- name: Deploy Nginx vhost
ansible.builtin.template:
src: site.conf.j2
dest: "/etc/nginx/sites-available/{{ nginx_server_name }}.conf"
owner: root
group: root
mode: "0644"
notify: Reload nginx Handlers run once at the end of the play when notified. That avoids reloading Nginx twelve times in one run.
PHP-FPM role task example
- name: Install PHP-FPM packages
ansible.builtin.apt:
name: "{{ php_packages }}"
state: present
- name: Ensure PHP-FPM is running
ansible.builtin.service:
name: "php{{ php_version }}-fpm"
state: started
enabled: true For Laravel 13 you need PHP 8.3 or higher. Laravel 12 runs on PHP 8.2+. Pin the version in group vars and keep staging aligned with production.
Deeper PHP-specific examples live in Ansible playbooks for PHP server provisioning. Pair that with application deploy docs from web development services when onboarding a new client server.
How Do You Run Ansible Playbooks Safely on Live Servers?
Production automation demands discipline. A playbook run as root can lock you out or wipe data. Treat playbooks like application code: branches, reviews, and staged rollout.
- Test on staging first. Mirror production PHP, MySQL, and OS versions.
- Use
--checkand--diff. Preview changes before applying them. - Limit blast radius with
-l. Run one host, verify, then the group. - Encrypt secrets with Vault. Never commit plain database passwords.
- Tag tasks. Run subsets:
--tags nginxduring a cert renewal. - Log runs in CI. GitLab CI or Jenkins archives output for audits.
Ansible Vault for secrets
ansible-vault create group_vars/web/vault.yml
ansible-vault edit group_vars/web/vault.yml Reference vaulted vars normally in tasks. Run with:
ansible-playbook -i inventory/production.ini playbooks/site.yml --ask-vault-pass Store the vault password in your CI secret store. See also Ansible Vault for secrets for rotation patterns.
ansible.cfg quality-of-life
[defaults]
inventory = inventory/production.ini
roles_path = roles
retry_files_enabled = False
host_key_checking = True
[privilege_escalation]
become = True
become_method = sudo Disable host key checking only in disposable lab VMs. On client production boxes, verify host keys.
On a booking platform like Adventure Third Pole Trek, drift happens when someone hot-fixes PHP-FPM pool settings over SSH. A weekly playbook run restores known-good config without redeploying Laravel code.
Ansible Playbooks vs Shell Scripts: Which Should You Use?
Shell scripts feel faster on day one. Playbooks pay off by month three when you manage three or more servers and repeat the same stack.
| Criterion | Ansible Playbook | Ad-hoc Shell Script |
|---|---|---|
| Idempotency | Built into modules; safe re-runs | You must write checks yourself |
| Agent required | No — SSH only | No — SSH only |
| Multi-host rollout | Native inventory and parallelism | Loop hosts manually |
| Secret handling | Ansible Vault integrated | Environment vars, often leaked |
| Learning curve | YAML + module docs | Bash familiarity |
| CI integration | Clean in GitLab CI, Jenkins | Works but harder to lint |
| Best fit | Ongoing config management | One-off migrations |
For a broader tool comparison, read Ansible vs Puppet vs Chef vs Salt. Puppet and Chef need agents. Ansible wins for lean teams running Ubuntu and Laravel.
Ansible does not replace Terraform for creating VPCs or RDS instances. Use Infrastructure as Code with Terraform for cloud resources. Use Ansible for what lives inside the VM.
CI example snippet
GitLab CI job to lint and dry-run:
ansible_lint:
stage: test
script:
- ansible-lint playbooks/
- ansible-playbook playbooks/site.yml -i inventory/staging.ini --check Wire this into a full pipeline using ideas from building a CI/CD pipeline with Jenkins or your existing GitLab config. Ongoing server care belongs in support and maintenance services when you hand off to a client team.
Common gotchas I see in production
- Wrong Python on target. Set
ansible_python_interpreterexplicitly on minimal images. - Becoming root without NOPASSWD sudo. Test
ansible web -m ping -bbefore long plays. - Using
commandorshelleverywhere. Prefer dedicated modules; they report changed status correctly. See the copy module documentation for file tasks. - Skipping handlers. Use
meta: flush_handlerswhen the next task depends on a reload. - Mixing app deploy into Ansible. Keep Composer and
artisan migratein Deployer. Ansible owns the platform layer.
Database recovery playbooks differ from config playbooks. For Postgres backups and restore drills, cross-read PostgreSQL point-in-time recovery playbook. Container teams may later add GKE or EKS, but bare-metal and VPS Laravel hosting remains common in Nepal.
Key Takeaways
- Ansible Playbooks declare desired server state in YAML and apply it over SSH with no agent.
- Start with inventory, a small base playbook,
--check, then expand into roles for PHP, Nginx, and security. - Split Terraform (cloud resources) from Ansible (OS and middleware) from Deployer (Laravel releases).
- Encrypt secrets with Ansible Vault and run playbooks from CI with linting and staged inventory.
- Re-run playbooks safely after drift; idempotent modules return
okwhen nothing needs changing. - Prefer modules over raw shell tasks, tag heavily, and test on staging before production limits go wide.
People Also Ask
Do I need to install anything on my servers to use Ansible playbooks?
No agent is required. Target hosts need SSH access, Python 3 (usually preinstalled on Ubuntu), and sudo for tasks that manage packages or services. The control node runs Ansible and connects outbound.
Can Ansible playbooks deploy Laravel application code?
They can, but most teams should not. Use Ansible for PHP-FPM, web server, firewall, and system users. Use Deployer, GitLab CI, or similar for Composer install, migrations, and symlink releases. Mixing both in one playbook blurs rollback boundaries.
How is Ansible Vault different from putting secrets in .env?
.env lives on the server and holds runtime app config. Vault encrypts infrastructure secrets—root DB passwords, API keys for provisioning—in Git so playbooks stay versioned without exposing credentials in plain text.
Is Ansible still relevant if we use Docker or Kubernetes?
Yes for hybrid setups. Many Laravel and WordPress clients still run on VPS or EC2 instances. Ansible configures those nodes efficiently. Containers shift some duties, but someone must still prepare hosts or golden images. Compare approaches in multi-cloud architecture guide before you over-engineer a small fleet.
Ship Repeatable Servers, Not Repeatable SSH Sessions
Ansible Playbooks: A Practical Guide is only complete once it runs in your repo—not after you read it once. Build a staging inventory this week. Convert your last manual LAMP setup into roles. Vault the passwords. Hook a dry-run into CI. The payoff is fewer midnight SSH fixes and servers that match each other.
If you want help designing playbooks for a Laravel fleet, PHP upgrade, or migration off manual setup, review the portfolio of production sites I maintain and reach out via contact us. For automation beyond servers—AI workflows, API glue, or full platform builds—see AI integration and automation services and read more on the blog, including notes from about me on fifteen years of shipping production systems. Client feedback on reliable delivery appears in customer reviews.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

