Manual Infrastructure #

Before we dive into Ansible’s syntax, playbooks, and modules, we first need to understand the root problem this technology is trying to solve. In the past, IT infrastructure management revolved around manual actions performed by system administrators directly on the target servers. This approach may have felt intuitive and adequate when you were only managing a handful of servers. However, with the demands of scalability, fast application release cycles, and the complexity of modern systems, this manual approach becomes unsustainable. This section takes a deep look at the dangers and limitations of managing infrastructure manually, and why an automation solution is an absolute necessity.

The Traditional Operational Philosophy and Modern Challenges #

In the previous decade, a system administrator’s job revolved around maintaining physical servers in the data center. When a new server was needed, the process started with ordering hardware, rack mounting it, connecting network cables, and installing the operating system from CD or USB. Once the base OS was ready, the administrator would log in over SSH (Secure Shell) and configure things one by one.

The server lifecycle back then was long-term. A server that was powered on could run for years without ever being shut down. This operational model focused on static stability.

But the modern IT industry demands a very different operational pace. With the rise of cloud technology, virtualization, containers, and DevOps methodologies, the server lifecycle has become highly dynamic:

  • Infrastructure is often ephemeral — servers can be created and destroyed within minutes to match traffic load capacity (autoscaling).
  • Development teams ship new application code several times a day, which often requires instant configuration adjustments on the server side.
  • Infrastructure scales rapidly, with a small operations team now having to manage hundreds or even thousands of VMs (Virtual Machines) simultaneously.

Relying on manual actions to manage servers at this dynamic scale will immediately cripple team productivity and increase the risk of business downtime.


The Manual Workflow in Detail: SSH and Direct Commands #

Let’s break down what happens when a system administrator configures a web server from scratch manually over SSH. The administrator has to open a terminal and run the following sequence of commands:

# Open an SSH connection to the target
ssh [email protected]

# Update the package repository index
sudo apt-get update

# Install the Nginx web server package
sudo apt-get install -y nginx

# Edit the default configuration file using a terminal text editor
sudo nano /etc/nginx/sites-available/default
# [The administrator manually makes line-by-line changes in the editor]

# Create the new application document root directory
sudo mkdir -p /var/www/my-web-app

# Set directory ownership so Nginx can access it
sudo chown -R www-data:www-data /var/www/my-web-app

# Restart the service to apply the new configuration
sudo systemctl restart nginx

Although it looks simple, every command line above involves micro-decisions made by a human under time pressure. For example:

  • Is the installed Nginx package version correct?
  • Were there any typos while editing /etc/nginx/sites-available/default?
  • Are the permissions on /var/www/my-web-app set to the strictest security level?

A small mistake in any of these steps can leave the server malfunctioning. This risk multiplies when the administrator has to perform the same configuration on a second server (web-prod-02) and a third (web-prod-03). They have to repeat every step manually, hoping their memory doesn’t skip a single detail.


Configuration Drift: The Hidden Enemy of Consistency #

One of the most tangible consequences of managing servers manually is configuration drift. Drift happens when servers that should be identical slowly diverge from one another because of ad-hoc changes made manually by different administrators over time.

Let’s look at a real-world example of configuration drift happening in an operations team:

How Configuration Drift Happens:
  1. Day 1: The team creates 3 web servers (web-01, web-02, web-03) with the same base configuration.
  2. Day 15: web-02 experiences memory overload. Administrator A logs into web-02 via SSH and raises the php-fpm memory limit to fix the emergency.
  3. Day 30: web-03 hits an SSL connection problem. Administrator B logs into web-03, updates the SSL certificate manually, and changes a cipher suite configuration line.
  4. Day 45: Administrator C is asked to release a new feature that needs a special library. They install it manually on web-01 and web-02, but forget to install it on web-03.

After 45 days, those three servers now have significantly different internal configurations. This problem is dangerous because:

  • A Debugging Nightmare: When the application errors out on one web server (say web-03), the team struggles to investigate because they don’t know which configuration parts differ on that server compared to the ones working normally.
  • Deployment Failure Risk: Automated deployment scripts designed on the assumption that all servers share the same base state will fail on servers whose configuration has drifted.

Snowflake Servers and the Danger of Technical Debt #

Martin Fowler, a renowned software architecture expert, coined the term Snowflake Server to describe a server with a unique, undocumented configuration that cannot be replicated automatically. Like snowflakes in the wild, no two server snowflakes have exactly the same internal shape.

Snowflake servers are usually born from years of accumulated ad-hoc manual actions, emergency hotfixes, and personnel changes within the IT team. The main characteristics of a snowflake server are as follows:

Snowflake Server Detection Checklist for Your Infrastructure:
  □ Nobody dares to reboot/restart that server for fear the services won't come back up.
  □ There's no written documentation or automation code to rebuild that server from scratch if its hard drive fails.
  □ Knowledge of how to manage that server lives only in one particular person's head.
  □ The operating system or libraries on that server are never updated for fear of breaking hidden dependencies.

The biggest danger of a snowflake server is vulnerability to operational disaster. If that server suffers hardware failure, the operations team is forced to spend days guessing and reconstructing the server’s configuration from scratch. This causes prolonged business downtime and massive financial losses.


Shell Scripts: Early Automation and Its Limitations #

To escape the drudgery of manual operations, the first step we usually take is writing shell scripts (.sh for Linux or .ps1 for Windows). These scripts wrap our manual terminal commands into a single file that can be executed in one go.

While writing shell scripts is a good first step toward automation, this method has fatal weaknesses when used for large-scale configuration management:

1. No Built-in Idempotency #

Shell scripts are inherently imperative (running commands step by step). They don’t care whether the target state already matches before executing a command.

Let’s look at the code comparison below to see how a traditional shell script fails to keep a system reliable compared to Ansible’s automation model:

# ANTI-PATTERN: Traditional shell script (Not Idempotent)
# On the first run, the script works fine.
# On the second run, it triggers errors because the directory already exists,
# the user is already registered, and configuration lines get duplicated in the target file!
mkdir /var/www/html/app
useradd -m -s /bin/bash appuser
echo "export APP_ENV=production" >> /etc/environment

To make the shell script above safe to run repeatedly, you have to hand-write a bunch of extra conditional code to validate system state:

# MITIGATION SOLUTION: A shell script forced to be idempotent manually
# The code becomes very long, convoluted, and hard to maintain as tasks grow.
if [ ! -d "/var/www/html/app" ]; then
    mkdir -p /var/www/html/app
fi

if ! id -u appuser >/dev/null 2>&1; then
    useradd -m -s /bin/bash appuser
fi

if ! grep -q "APP_ENV=production" /etc/environment; then
    echo "export APP_ENV=production" >> /etc/environment
fi

2. Inconsistent Output (Lack of Standard Output) #

Shell scripts have no standard way of reporting execution status. Some scripts write logs to custom files, some write nothing on success, and others produce error messages without returning the proper exit code. This makes it hard to build automated monitoring on top of shell scripts.


Script Scalability Limits #

The biggest weakness of shell scripts appears when you try to run the same automation across many servers in parallel. Shell scripts were never natively designed to handle mass SSH connection management.

Usually, you’re forced to write a wrapper script using a for loop to distribute the script to every server:

# Wrapper script for distributing shell automation
for host in web-01.local web-02.local web-03.local web-04.local; do
  scp setup-app.sh admin@$host:/tmp/
  ssh admin@$host "bash /tmp/setup-app.sh"
done

The sequential loop flow above carries a very high risk of orchestration failure. Let’s visualize that failure scenario:

flowchart TD
    Start["Run the wrapper loop script over SSH"] --> S1["1. Send & Execute on web-01 (Success)"]
    S1 --> S2["2. Send & Execute on web-02 (Failed: Network Timeout)"]
    S2 -- "Execution Stops Immediately!" --> Failure["Wrapper script halts with an Error Exit Code"]
    Failure -.-> Check{"Current Infrastructure State:\n- web-01: Fully configured\n- web-02: Broken/Partially configured\n- web-03 to 04: Untouched by configuration"}

When the loop stops mid-way because of a connection failure on one server:

  • There’s no built-in mechanism to resume execution only on the servers that haven’t been configured yet.
  • There’s no automatic rollback feature to return a half-configured server to a safe original state.
  • You’re forced to manually audit each server one by one to confirm the target’s current state — which eats up enormous operational time again.

Summary #

  • Manual Management Doesn’t Scale — Managing infrastructure manually over SSH limits the operations team’s speed and increases the risk of failure from human cognitive error.
  • Configuration Drift — Emerges as a logical consequence of manual ad-hoc modifications, producing servers with hidden internal configuration differences.
  • Snowflake Servers — Present a high level of operational disaster risk because infrastructure can’t be instantly rebuilt when hardware fails.
  • Shell Scripts Aren’t a Long-Term Solution — Because they lack built-in idempotency and a standard status-reporting system, shell scripts become very hard to maintain as server complexity grows.
  • Sequential Orchestration Failures — The traditional SSH loop approach in shell scripts can’t handle fault tolerance and reliable target-server state recovery.

← Previous: What is Ansible Next: Alternatives →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact