By Igor Gomes
A DevOps-focused academic project created at Nackademin to practice Infrastructure as Code (IaC), configuration management and Linux server automation with Ansible.
The project uses inventories, playbooks, reusable roles, templates and encrypted variables to configure web and database servers, apply security controls and deploy basic monitoring.
An Ansible-based infrastructure automation project for configuring Linux web and database servers in a repeatable and structured way.
Built to practice configuration management, reusable automation and Infrastructure as Code instead of performing server configuration manually.
The project demonstrates how Ansible can centralize server configuration, separate responsibilities through roles and automate recurring infrastructure tasks.
This is an academic infrastructure automation project. It focuses on configuration management of existing Linux hosts rather than provisioning cloud infrastructure.
flowchart LR
A[Ansible Control Node]
A --> B[Web Server]
A --> C[Database Server]
B --> D[Apache]
B --> E[Node Exporter]
C --> F[MariaDB]
C --> G[Node Exporter]
H[Prometheus]
H --> E
H --> G
The Ansible control node manages two server groups defined in the inventory:
webb_serversdatabas_servers
The main playbook applies dedicated roles to each group. Once deployed, Node Exporter exposes host metrics, and Prometheus collects monitoring data from both managed servers.
flowchart TD
A[main.yml]
A --> B[Inventory]
A --> C[group_vars]
A --> D[Roles]
A --> E[Playbooks]
B --> B1[hosts]
C --> C1[all.yml]
C --> C2[vault_vars.yml]
D --> D1[webbserver]
D --> D2[dbserver]
D --> D3[geerlingguy.firewall]
D1 --> W1[Apache]
D1 --> W2[Jinja2 Templates]
D2 --> DB1[MariaDB]
E --> P1[Prometheus]
E --> P2[Node Exporter]
E --> P3[Compliance]
E --> P4[Hostname]
E --> P5[Timezone]
| Technology | Purpose |
|---|---|
| Ansible | Configuration management and automation |
| Linux | Managed server environment |
| YAML | Playbooks, inventories and configuration |
| Jinja2 | Apache configuration templating |
| Apache HTTP Server | Web server |
| MariaDB | Database server |
| Ansible Vault | Encrypted variables |
| Prometheus | Metrics collection |
| Node Exporter | Linux host metrics |
| Docker | Local monitoring containers |
The webbserver role automates:
- Apache installation
- Apache service startup and enablement
- Virtual Host configuration from a Jinja2 template
- Document root creation
- Deployment of a sample
index.html - Global Apache
ServerNameconfiguration - Creation of local users
The dbserver role automates:
- MariaDB installation
- MariaDB service startup and enablement
- Installation of the Python MySQL dependency required by Ansible
- Creation of the
webappdbdatabase - Creation and permission configuration of the application database user
- Deployment of supporting files
The repository contains automation for several security-related tasks:
- encrypted variables with Ansible Vault
- firewall configuration with a default deny policy
- different allowed ports for web and database hosts
- removal of passwordless sudo for the deployment user
- compliance checks for selected AlmaLinux 9 settings
- checks for unnecessary services and packages
- validation of sensitive file permissions
- USB storage module checks
Monitoring is configured with Prometheus and Node Exporter.
Node Exporter is installed as a systemd service on managed hosts, while Prometheus and a local Node Exporter instance can run as Docker containers on the control node.
The Prometheus configuration includes the managed web and database servers as scrape targets.
The playbooks/ directory contains focused automation for individual tasks:
| Playbook | Purpose |
|---|---|
configure_firewall.yml |
Configure firewall rules |
install_node_exporter.yml |
Install and enable Node Exporter |
prometheus_setup.yml |
Configure and start Prometheus monitoring |
compliance_check.yml |
Run selected compliance checks |
compliance.yml |
Run additional compliance validation |
set_hostname.yml |
Set hostnames from the Ansible inventory |
tzone.yml |
Configure the CET timezone |
The repository also contains remove_passwordless_sudo.yml for tightening sudo configuration.
Before running the playbooks, make sure you have:
- Ansible installed on the control node.
- SSH access to the target hosts defined in
hosts. - The required external Ansible roles installed.
Install the firewall role with:
ansible-galaxy role install geerlingguy.firewallThe included ansible.cfg already points Ansible to the local hosts inventory and roles directory.
Run the main configuration:
ansible-playbook main.yml --ask-vault-passRun a specific playbook:
ansible-playbook playbooks/configure_firewall.ymlExample monitoring setup:
ansible-playbook playbooks/install_node_exporter.yml
ansible-playbook playbooks/prometheus_setup.ymlThe inventory contains environment-specific IP addresses and SSH configuration from the original lab environment. These values need to be adapted before running the project in another environment.
Ansible-master/
├── ansible.cfg
├── hosts
├── main.yml
├── deploy_visitor.yml
├── remove_passwordless_sudo.yml
├── group_vars/
│ ├── all.yml
│ └── vault_vars.yml
├── host_vars/
│ └── webb
├── playbooks/
│ ├── compliance.yml
│ ├── compliance_check.yml
│ ├── configure_firewall.yml
│ ├── install_node_exporter.yml
│ ├── prometheus_setup.yml
│ ├── set_hostname.yml
│ └── tzone.yml
└── roles/
├── webbserver/
│ ├── files/
│ ├── handlers/
│ ├── tasks/
│ └── templates/
├── dbserver/
│ ├── files/
│ └── tasks/
└── geerlingguy.firewall/
Igor Gomes — DevOps Engineer
Email: igor.gomes.u@gmail.com
LinkedIn: Igor Gomes
GitHub: igor-gomes-u