This project demonstrates a production-ready approach to Infrastructure as Code (IaC) for security research environments. It automates the provisioning of a complete DevSecOps Laboratory on Proxmox VE, utilizing OpenTofu for state management and Cloud-Init for instance bootstrapping.
Designed as a showcase of DevSecMLOps principles, this repository implements a reproducible, modular, and verified infrastructure pipeline that deploys:
- Observability & Security: A fully configured Wazuh SIEM server for log analysis and security monitoring.
- Target Infrastructure: A Rails Application server for vulnerability assessment and security testing.
- Research & Defense: A transparent Hardening Lab for testing security policies and configuration management.
- Modular IaC Architecture: Uses custom, reusable Terraform modules (
modules/vm) to enforce consistency, scalability, and DRY (Don't Repeat Yourself) principles across environments. - Automated Verification: Includes a custom validation framework (
tests/validate.sh) written in Bash andjqto perform integration testing on deployed infrastructure, ensuring reliable delivery. - Zero-Touch Provisioning: Leverages Cloud-Init to fully bootstrap VMs with users, SSH keys, and network configurations effectively eliminating manual setup.
- Tool Agnostic Design: Built for OpenTofu but maintains 100% compatibility with Terraform v1.x, demonstrating flexibility in tooling choices.
The infrastructure consists of three main VMs connected via a bridge network on the Proxmox node.
graph TD
subgraph Proxmox Node
Bridge[vmbr0]
end
subgraph VMs
Wazuh[Wazuh Server<br>192.168.168.71]
Rails[Rails App<br>192.168.168.72]
Hardening[Hardening Lab<br>192.168.168.73]
end
Bridge --- Wazuh
Bridge --- Rails
Bridge --- Hardening
Ensure you have the following tools installed:
Configuration is managed via variables.tf. You should create a terraform.tfvars file (based on terraform.tfvars.example if available) to set these values. Do not commit terraform.tfvars to version control.
| Variable | Description | Default | Required |
|---|---|---|---|
environment |
Environment name | lab |
No |
proxmox_api_url |
Proxmox API URL (e.g., https://proxmox:8006/api2/json) |
- | Yes |
proxmox_api_token_id |
Proxmox API Token ID | - | Yes |
proxmox_api_token_secret |
Proxmox API Token Secret | - | Yes |
proxmox_node |
Proxmox Node Name | - | Yes |
ssh_public_key |
SSH Public Key for VM access | - | Yes |
proxmox_default_storage |
Default storage for volumes | local |
No |
disk_format |
Disk format (e.g., qcow2, raw) | qcow2 |
No |
proxmox_tls_insecure |
Disable SSL verification | true |
No |
template_name |
Base VM template name to clone | - | Yes |
storage |
Storage for VM disks | local-lvm |
No |
network_bridge |
Network bridge interface | vmbr0 |
No |
network_vlan |
VLAN tag (-1 for none) | -1 |
No |
cloud_init_user |
Default Cloud-Init user | ubuntu |
No |
wazuh_server_ip_config |
IP Config for Wazuh Server | ip=192.168.168.71/24,gw=192.168.168.1 |
No |
rails_app_ip_config |
IP Config for Rails App | ip=192.168.168.72/24,gw=192.168.168.1 |
No |
hardening_lab_ip_config |
IP Config for Hardening Lab | ip=192.168.168.73/24,gw=192.168.168.1 |
No |
A Makefile is provided to simplify common operations.
Initialize the project and download providers:
make initGenerate an execution plan to see what changes will be made:
make planApply the changes to create the infrastructure:
make applyOnce the VMs are up and running, you can quick-connect to them using:
# Connect to Hardening Lab
make ssh-hardening
# Connect to Wazuh Server
make ssh-wazuh
# Connect to Rails App
make ssh-railsCheck the status and IP addresses of all VMs:
make statusValidate that all VMs are running correctly:
make validateTo destroy all infrastructure (WARNING: This will delete all VMs):
make destroyClean up temporary OpenTofu files and logs:
make cleanThis project uses Ansible for post-provisioning configuration and software installation. The Ansible structure is organized as follows:
- Inventory:
ansible/inventory/hosts.ini(Defining groups forwazuh,rails, etc.) - Playbooks:
site.yml: Main entry point.base-setup.yml: Applies common configurations and hardening to all nodes.docker-install.yml: Installs Docker on required nodes (e.g., Wazuh).
- Roles: Modular tasks for specific functions (
common,docker,ssh-hardening).
The ansible/Makefile provides convenient shortcuts for common tasks:
-
Check Connectivity:
make -C ansible ping
-
Apply Base Configuration: Installs common utilities and applies SSH hardening.
make -C ansible base
-
Install Docker: Deploys Docker to the Wazuh server.
make -C ansible docker
-
Run All Playbooks: Executes the full site configuration.
ansible-playbook -i ansible/inventory/hosts.ini ansible/playbooks/site.yml