⚙️ DevOps Simplified: Automating Fullstack Deployment with Ansible in Under 5 Minutes

Table of contents
- 🧩 Overview
- 🚀 Why Use Ansible?
- 🛠️ Prerequisites
- 🏗️ Step 1: Installing Ansible
- 📡 Step 2: Define Your Inventory
- 📶 Step 3: Test Connectivity
- 📦 Step 4: Bootstrap the Server with Essential Tools
- 🚀 Step 5: Deploy the Fullstack Application
- 📁 BONUS: Copy Local Files to the Server
- 📌 Key Concepts Recap
- 🧠 Final Thoughts
- 📎 Suggested Improvements & Next Steps

🧩 Overview
In the dynamic world of DevOps, repeatable infrastructure is gold. A few days ago, I faced a challenge as a DevOps engineer: wipe a cluttered VPS and redeploy a fullstack application on Hostinger from scratch. Instead of falling into the manual trap, I decided to automate everything using Ansible, the lightweight yet powerful automation engine.
This article walks through a real-world DevOps story—how I went from a messy server to a fully provisioned, production-ready environment in minutes, using Ansible playbooks.
🚀 Why Use Ansible?
Ansible is an open-source IT automation tool designed for configuration management, application deployment, and orchestration. What makes it stand out?
✅ Agentless (no software required on the server)
✅ Simple YAML syntax (human-readable)
✅ Powerful at scale (from 1 server to 10,000+)
🛠️ Prerequisites
You’ll need:
A local machine with Ansible installed
A remote VPS (e.g., Hostinger KVM server) with SSH or password access
SSH communication between master and host must work
⚠️ If your server uses a private IP (e.g., behind a NAT or firewall), or you're on a different network, you may need a VPN to establish connectivity.
Ensure that your master machine canssh
into the host — otherwise, Ansible playbooks will not execute.
🏗️ Step 1: Installing Ansible
On Ubuntu / Debian:
sudo apt update && sudo apt install ansible -y
On Arch Linux / EndeavourOS:
sudo pacman -S ansible
On macOS:
brew install ansible
Verify the installation:
ansible --version
📡 Step 2: Define Your Inventory
Create an inventory file to define your remote servers:
# inventory/hosts.yml
all:
hosts:
appserver:
ansible_host: 1.2.3.4
ansible_user: root
ansible_ssh_pass: "your_password"
children:
webservers:
hosts:
appserver:
📝 You can later switch to SSH keys or add multiple servers here for mass deployments.
📶 Step 3: Test Connectivity
Let’s ensure Ansible can communicate with your server:
# ping.yml
- name: Test server connectivity
hosts: webservers
gather_facts: false
tasks:
- name: Ping the server
ansible.builtin.ping:
- name: Confirm reachability
ansible.builtin.debug:
msg: "Server is reachable and ready!"
Run the playbook:
ansible-playbook -i inventory/hosts.yml ping.yml
✅ You should see a success response—Ansible is ready to roll!
📦 Step 4: Bootstrap the Server with Essential Tools
Now, let’s install Git, Docker, and other useful packages:
# playbooks/bootstrap.yml
- name: Install essential DevOps tools
hosts: webservers
become: yes
tasks:
- name: Update APT cache
ansible.builtin.apt:
update_cache: yes
- name: Install core packages
ansible.builtin.apt:
name:
- git
- curl
- ca-certificates
- gnupg
- lsb-release
state: present
- name: Add Docker’s GPG key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repo
ansible.builtin.apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release | lower }} stable"
state: present
- name: Install Docker and Compose
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: latest
- name: Add user to docker group
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: yes
Run it:
ansible-playbook -i inventory/hosts.yml playbooks/bootstrap.yml
⏱️ In under 4 minutes, your server is ready to host applications.
🚀 Step 5: Deploy the Fullstack Application
Here’s a playbook to clone your GitHub repo and run docker compose up
.
# playbooks/deploy.yml
- name: Deploy fullstack app
hosts: webservers
become: yes
vars:
project_dir: /opt/fullstack-app
repo_url: https://github.com/your/repo.git
tasks:
- name: Ensure project directory exists
ansible.builtin.file:
path: "{{ project_dir }}"
state: directory
mode: '0755'
- name: Clone repository
ansible.builtin.git:
repo: "{{ repo_url }}"
dest: "{{ project_dir }}"
force: yes
- name: Start app with Docker Compose
ansible.builtin.shell: docker compose up -d
args:
chdir: "{{ project_dir }}"
Run the deployment:
ansible-playbook -i inventory/hosts.yml playbooks/deploy.yml
🎯 Boom! You now have a working fullstack app up and running.
📁 BONUS: Copy Local Files to the Server
Sometimes you need to ship custom config files or scripts with your playbooks.
Step 1: Create a files/
directory
mkdir -p files
echo "ENV=production" > files/.env
Step 2: Add a copy task in your playbook
- name: Copy .env file to server
ansible.builtin.copy:
src: files/.env
dest: "{{ project_dir }}/.env"
owner: root
group: root
mode: '0644'
You can also copy whole folders:
- name: Copy scripts directory
ansible.builtin.copy:
src: files/scripts/
dest: "{{ project_dir }}/scripts/"
owner: root
group: root
mode: '0755'
recurse: yes
🛡️ This ensures all custom files are shipped with your deployment—secure, consistent, and version-controlled.
📌 Key Concepts Recap
Concept | Description |
Inventory | Stores IPs and access credentials of your hosts |
Playbook | Defines tasks to be executed on remote servers |
Tasks | Actions such as installing packages or copying files |
Modules | Predefined tools like apt , git , ping , copy , file , and shell |
Idempotency | Ansible won't repeat tasks unnecessarily if already done |
🧠 Final Thoughts
This experience cemented my belief in infrastructure as code. Whether you’re a solo developer or managing thousands of servers, Ansible empowers you to:
Eliminate manual errors
Automate routine tasks
Speed up recovery and deployment
Standardize infrastructure effortlessly
So the next time you're staring at a server wondering where to start, ask yourself:
Can I Ansible this?
💡 Yes, and you absolutely should.
📎 Suggested Improvements & Next Steps
Add role-based structure for reusability
Implement Ansible Vault for securing passwords
Add monitoring stack (Prometheus + Grafana)
Configure automatic SSL and reverse proxy (Nginx)
Use SSH keys instead of passwords
Subscribe to my newsletter
Read articles from Shad Reza directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
