All posts
ansibledevopsautomation

Ansible: A Practical Guide for Full-Stack Developers

A practical guide to Ansible — agentless configuration management and automation for servers you already have running.

SR

Suhail Roushan

August 6, 2026

·
4 min read
·
0 views

Terraform answers "what infrastructure should exist"; Ansible answers "what should be configured on the infrastructure that already exists" — and the distinction matters more than it first appears once you're managing real servers over time.

Ansible is an agentless configuration management and automation tool that connects to servers over SSH and executes declarative "playbooks" describing the desired state of that server — packages installed, files in place, services running. Unlike some configuration management tools, it requires no agent installed on target machines, just SSH access and Python, which makes it easy to adopt against existing infrastructure without any prior setup on the servers themselves.

Why Ansible Matters (and When to Skip It)

Manually SSHing into servers to install packages, update configuration files, or restart services doesn't scale past a couple of machines, and it's not reproducible or auditable. Ansible playbooks describe the desired end state declaratively — running the same playbook repeatedly is safe (idempotent), converging any server toward that state regardless of its starting condition.

Skip Ansible for purely containerized/serverless infrastructure where there's no persistent server to configure — its value is specifically in managing the configuration of long-lived machines, which matters less if your infrastructure is entirely ephemeral containers managed by Kubernetes or a PaaS.

Getting Started with Ansible

An inventory file listing target servers:

# inventory.ini
[webservers]
web1.example.com
web2.example.com

A playbook describing desired state:

# deploy.yml
- hosts: webservers
  become: yes
  tasks:
    - name: Install Node.js
      apt:
        name: nodejs
        state: present

    - name: Copy application files
      copy:
        src: ./dist/
        dest: /var/www/app/

    - name: Ensure app service is running
      systemd:
        name: my-app
        state: started
        enabled: yes
ansible-playbook -i inventory.ini deploy.yml

Core Ansible Concepts Every Developer Should Know

Idempotency is the core design principle. Running the same playbook twice produces the same end state, not duplicate actions — a task like "ensure this package is installed" checks current state first and only acts if a change is actually needed, which is what makes playbooks safe to re-run routinely.

Roles organize playbooks into reusable, composable units. Rather than one massive playbook, roles package related tasks, templates, and variables (a "database" role, a "webserver" role) that can be shared and reused across projects:

- hosts: webservers
  roles:
    - common
    - nodejs
    - nginx

Templates generate configuration files dynamically using variables, letting one template produce environment-specific config files (an nginx config with the right domain and port per environment):

# templates/nginx.conf.j2
server {
    listen 80;
    server_name {{ domain_name }};
    proxy_pass http://localhost:{{ app_port }};
}

Variables and inventory groups let one set of playbooks target different environments with different configuration values, avoiding duplicated playbooks per environment.

Common Ansible Mistakes and How to Fix Them

Mistake 1: writing tasks that aren't actually idempotent (using raw shell commands instead of Ansible's built-in modules, which handle idempotency for you). Fix: prefer Ansible's declarative modules (apt, copy, systemd) over shell/command tasks wherever an equivalent module exists.

Mistake 2: hardcoding environment-specific values directly in playbooks. This prevents reusing the same playbook across staging and production. Fix: use variables and inventory groups to parameterize environment differences.

Mistake 3: not testing playbooks against a non-production environment first. Running an untested playbook change directly against production servers risks unexpected side effects at scale. Fix: test against a staging environment or a local VM before running any significant playbook change against production infrastructure.

When Should You Use Ansible Instead of Terraform?

Use Ansible for configuring and managing software on servers that already exist — package installation, file management, service configuration. Use Terraform for provisioning the infrastructure itself (creating the servers, networking, databases). Many real-world setups use both together: Terraform provisions the infrastructure, Ansible configures what runs on it.

Ansible in Production

Keep playbooks in version control and treat changes to them with the same review discipline as application code — a playbook is effectively a program that modifies production servers. Also use --check (Ansible's dry-run mode) before applying significant changes to production, similar in spirit to reviewing a Terraform plan before applying it.

If you're managing more than a couple of long-lived servers by hand via SSH, that's the point where Ansible's automation starts paying for its setup cost — start with your most frequently repeated manual task.

Related posts

Written by Suhail Roushan — Full-stack developer. More posts on AI, Next.js, and building products at suhailroushan.com/blog.

Get in touch