Introduction
The way in which IT infrastructure is provided and operated has changed significantly in recent decades. In the early years of system administration, everyday life consisted of manually installing individual servers, importing software packages, editing configurations directly in files and starting services. This was not only time-consuming, but also error-prone and difficult to reproduce. Even a small difference in a configuration could lead to problems that were almost impossible to trace.
With increasing digitalization, virtualization and later cloud technologies, the demands on IT environments have increased enormously. Companies suddenly no longer needed just individual servers, but entire landscapes consisting of dozens or hundreds of systems that had to be provided consistently and quickly. At the same time, new requirements for traceability, compliance and automation arose. This is where the Infrastructure as Code (IaC) concept came into its own.
The basic idea of IaC is as simple as it is powerful: infrastructure is no longer built manually, but described as code. This code defines the desired target state of an environment and ensures that it is achieved automatically. This means that infrastructure is treated in exactly the same way as software: it can be versioned, checked, tested and automated.
IaC is particularly interesting in combination with modern tools such as Ansible and platforms such as GitLab. Ansible makes it possible to describe and reliably configure server and application environments with clearly readable YAML playbooks. GitLab complements this way of working with the principles of software development: version control, code reviews and CI/CD pipelines. This creates a complete workflow: from the description of the infrastructure to automation and controlled rollout in productive environments.
In this article, we first take a look at the philosophy of IaC, then go into the history of the approach and finally use an advanced Ansible example to show how IaC is implemented in practice. The final step is the integration into GitLab CI/CD in order to consistently use the methods from software development for infrastructure as well.
The history of IaC
The idea of infrastructure as code goes back a long way. As early as 1993, CFEngine introduced the principle of convergence: systems automatically move to a defined target state. With Puppet (2005) and Chef (2009), these approaches became suitable for mass use – for the first time, large data centers could be managed declaratively and consistently.
In 2012, Ansible took the decisive step towards simplification: agentless, easy to read in YAML and therefore also attractive for smaller teams. Shortly afterwards, Terraform was created, a tool that expanded the focus from pure configuration to provisioning and made cloud resources manageable across platforms via code.
Today, IaC is inextricably linked to DevOps and CI/CD: Platforms such as GitLab ensure that infrastructure code is versioned, checked and rolled out automatically. The history of IaC thus shows a clear line: not a trend, but a consistent development over decades – with unchanged high relevance.
The philosophy of IaC
Infrastructure as Code is much more than a technical tool or an automation framework. It is a way of thinking that is fundamentally changing the way we deal with infrastructure. While classic administration was often reactive – “a problem occurs, so we log in and fix it” – IaC shifts the focus to a proactive, plannable and verifiable model.
1. from the handle to the target state
In the traditional approach, an administrator describes work steps: “Install package X”, “Change line Y in the configuration”, “Restart service Z”. IaC, on the other hand, describes states: “The web server is installed and running”, “The firewall allows port 80”. As a result, the path fades into the background and the goal takes center stage.
This distinction is crucial: scripts reproduce commands, IaC reproduces results.
2. repeatability and idempotency
A central principle is idempotency. If an IaC playbook is executed several times, there are no unexpected side effects. Ansible modules, for example, always check whether a desired state has already been reached before making a change. This means that infrastructure does not “drift apart”, but always converges back to the defined target state.
3. infrastructure becomes code
By describing infrastructure in declarative files, it becomes part of the same ecosystem as software:
- Changes are stored in Git repositories.
- Adjustments are discussed via merge requests.
- Quality is ensured by tests and pipelines.
This removes the dividing line between developers and administrators: Infrastructure is just as versionable, verifiable and automatable as application code.
4. cooperation instead of insular knowledge
In the past, it was often like this: “Only admin X knows how to set up the server.” This risk disappears with IaC. The code serves as living documentation: everyone in the team can understand how systems are structured and changes are transparent. In this way, knowledge is shared and not hidden in the heads of individuals.
5 Speed and safety are not mutually exclusive
A frequently heard accusation is: “Automation is dangerous, you lose control.” In reality, the opposite is the case. Without IaC, every manual change leads to a deviation that is not documented. With IaC, on the other hand, every change is visible, can be checked and, in case of doubt, can also be reset. This not only increases the speed of provision, but also security and traceability.
6 IaC as part of the DevOps concept
IaC fits seamlessly into the ideas of DevOps. Developers and administrators talk about the same code, work in the same repository and use the same processes. Ansible describes the desired system state, GitLab CI/CD takes care of automated execution, tests and checks. Infrastructure is no longer operated “on the side”, but is actively integrated into development and delivery processes.
Practice: A web server with Ansible
Playbook and role structure
- name: Provisioniere Webserver mit Ansible
hosts: webserver
become: yes
roles:
- common
- nginx
Role common: Basic packages and firewall rules.
Role nginx: Installation, configuration via template, handler for reload.
Example template:
server {
listen {{ nginx_listen_port }};
server_name {{ nginx_server_name }};
location / {
root /var/www/html;
index index.html;
}
}Philosophy in action:
- State instead of commands: “Nginx runs with this config”, not “run apt-get”.
- Repeatable: One host or a hundred – the result is the same.
- Traceable: Every change is visible as a Git diff.
From code to pipeline: Ansible with GitLab CI/CD
A playbook in the repository is valuable – but IaC only becomes really strong when changes are automatically checked and applied. With CI/CD, GitLab offers an ideal platform for this. The basic idea is that every change to infrastructure code goes through the same life cycle as software – commit, review, tests and deployment.
Example .gitlab-ci.yml
stages:
- lint
- test
- deploy
ansible-lint:
stage: lint
image: cytopia/ansible-lint
script:
- ansible-lint playbooks/site.yml
ansible-dry-run:
stage: test
image: willhallonline/ansible:latest
script:
- ansible-playbook -i inventories/prod playbooks/site.yml --check --diff
deploy-prod:
stage: deploy
image: willhallonline/ansible:latest
script:
- ansible-playbook -i inventories/prod playbooks/site.yml
only:
- main
Explanation
Linting (quality assurance)
In the first stage, ansible-lint checks whether the playbooks are syntactically correct and comply with common best practices. Errors such as incorrect indents or unsafe modules are detected at an early stage – before anything is rolled out at all.
Dry-Run (Tests)
A test run is started at --check --diff. Ansible shows which changes would be necessary without actually implementing them. Differences in configuration files are also displayed. This allows reviewers and administrators to understand whether a merge has the desired effects.
Deployment (productive rollout)
The playbook is only actually executed in the deploy-prod job if all tests were successful. GitLab ensures that this step only runs in the main branch – i.e. after the change has been checked and released via Merge Request. This avoids inadvertent snap shots.
Why GitLab + Ansible fit so well with the IaC philosophy
- Version control: Every change is documented via commits and merge requests.
- Transparency: Pipelines run automatically and clearly show what happens where and when.
- Traceability: Linting, dry runs and diffs make the effects visible before anything goes live.
- Security: Rollouts only take place after a review and successful pipeline.
- Automation: Infrastructure is treated like software – no more manual “playbook triggering”.
Conclusion
Infrastructure as Code has come a long way – from CFEngine to Puppet and Chef to modern workflows with Ansible and GitLab CI/CD. The approach is not new, but it is more relevant than ever: without IaC, it would hardly be possible to operate complex and dynamic infrastructures in a reproducible, traceable and secure manner.
Ansible shows in practice how the IaC philosophy is implemented: declarative, modular and idempotent. GitLab CI/CD extends this approach to include the tools of software development – versioning, reviews, tests and automated deployments. Together, they create an end-to-end workflow that provides both stability and speed.
For many organizations, however, getting started with IaC is a challenge: Which tools fit the existing environment? How do you build playbooks and roles sustainably? How do you integrate GitLab pipelines so that they support processes securely and reproducibly? And how can teams be prepared for this new way of working?
This is exactly where NETWAYS can help: with consulting tool selection, best practices for architecture and playbooks, training courses for teams and support for operation and further development. This means that IaC is not only understood as a concept, but also successfully applied in everyday life.


















