From Manual SSH to Ansible: My First Steps with Infrastructure as Code

2-minute read

Background

In the past few months, I was learning about DevOps, AWS Cloud, Linux Administration, and the cloud in general; therefore, I ran into a term called ==IaC==, Infrastructure as Code.

It was an interesting topic to explore. Infrastructure as Code — it’s not a service, but it’s a method. And by “a method,” I mean you can use it in whatever way you want. My definition for IaC is that it’s a method that allows you to configure your server using only code.

For example, you have services running on overseas VPS instances, primarily due to network connectivity and cost considerations. The VPS provider might occasionally change. Each time I migrate servers, sshing to the new VPS and installing packages by manually copying commands, the process becomes relatively cumbersome.

A quick approach would be writing a bash script to install Docker on the new VPS, then a Docker Compose file to run your services like Nginx, and you’re done. Imagine you’re working with someone and he needs to know which packages you installed, which version of Postgres you installed, and which web server you’re using. I’m sure your teammates are smart and would figure that out. But Ansible seems like a more elegant solution, so I decided to give it a try.

Ansible - Agentless Remote Configuration of Linux Servers

Configuring a new Linux VPS isn’t that hard, but doing that repeatedly for migrations or for managing multiple machines can get messy.

Ansible is owned by Red Hat (anything that comes from these guys, I trust 100%). It’s Python-based, agentless, uses SSH, and most importantly, it’s free. Although there’s a paid version, the open source one will do just fine.

Ansible’s official documentation is quite clear and beginner friendly. you can start with the basics very easily.

To start using Ansible, a simple setup looks like this:

  1. Install Ansible on your local machine
  2. Define your inventory (VPS connection details) and write a playbook (desired state of the VPS).
  3. Run the playbook locally. Ansible uses SSH to connect and configure the VPS, bringing it to the defined state.
- name: Install Nginx
    ansible.builtin.apt:
      name: nginx
      state: present
      update_cache: true

- name: Ensure Nginx is running
    ansible.builtin.service:
      name: nginx
      state: started
      enabled: true

Ansible works by installing it first, then writing your instructions in .yml text files. As a starting point, you create an ansible.cfg (which holds Ansible’s configuration) and an inventory file such as hosts.yml (which lists the hosts you’ll manage).

In addition, Ansible has a recommended folder structure called a role. A playbook is a file that contains one or more plays, and each play runs its own tasks (like the block above); a role just lets you organize those tasks, variables, and files into reusable folders.

Compared with Docker Compose, Ansible is more flexible and powerful. It can directly manage system-level configurations, and — like a bash script — can even install and run Docker itself. But unlike bash, Ansible uses clean, readable YAML and is idempotent: running it multiple times won’t cause conflicts. It’s also much easier to maintain and modify than bash.

Now, I can perform migrations from one server to another. I just need to update the inventory file and rerun the playbook. The new VPS will be fully provisioned automatically. This greatly improves efficiency, reduces human error, and gives me more confidence and flexibility when adjusting my infrastructure.

Summary

This is my first experience with IaC. Ansible is easy to get started with, just a simple configuration, lightweight, and perfect for individual developers. The benefits? Greater consistency, better scalability, and a huge reduction in manual, repetitive work.