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

Shad RezaShad Reza
5 min read

🧩 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 can ssh 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

ConceptDescription
InventoryStores IPs and access credentials of your hosts
PlaybookDefines tasks to be executed on remote servers
TasksActions such as installing packages or copying files
ModulesPredefined tools like apt, git, ping, copy, file, and shell
IdempotencyAnsible 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

0
Subscribe to my newsletter

Read articles from Shad Reza directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Shad Reza
Shad Reza