Many think IaC (Infrastructure as Code) is only for AWS, Azure, or other cloud platforms.
But what if you don’t have access to public or private cloud resources?
I built a solution that lets you start with Terraform + Ansible using only VirtualBox locally:
🔹 Terraform → provisions the environment
🔹 Vagrant → manages VM lifecycle
🔹 VirtualBox → runs the virtual machine
🔹 Ansible (inside WSL) → configures the VM (installs & starts Nginx)
🔹 GitHub Actions → orchestrates the entire workflow (CI/CD style)
📌 The outcome:
âś… A fully automated VM setup (Ubuntu on VirtualBox)
âś… Nginx web server running & accessible
✅ Same IaC workflow as in the cloud — but on your local machine
This approach is perfect for learning, testing, and practicing DevOps pipelines without spending on cloud resources.
🎯 Project Objective
The goal is to automate the deployment of a local infrastructure (a VirtualBox VM) and configure it with Ansible to run Nginx — all orchestrated via IaC tools and CI/CD.
đź› Tools Used
- VirtualBox → virtualization software to host the VM
- Vagrant → manages VM lifecycle in a simple workflow
- Terraform → declaratively provisions infrastructure
- Windows Subsystem for Linux (WSL) → runs Linux tools on Windows (needed for Ansible)
- Ansible → configuration management & app deployment
- GitHub Actions → CI/CD automation
⚙️ Setup & Installation
1. Install VirtualBox
- Enable virtualization (Intel VT-x / AMD-V) in BIOS/UEFI.
- Download VirtualBox and install it.
- (Optional but recommended) Install the VirtualBox Extension Pack.
- Verify by launching VirtualBox Manager.
2. Install Terraform
- Download Terraform.
- Extract
terraform.exe
toC:terraform
. - Add it to PATH.
- Verify:
terraform version
3. Install Vagrant
- Download Vagrant.
- Install via the
.msi
file. - Restart your system.
- Verify:
vagrant --version
4. Install WSL & Ansible
- Enable WSL:
wsl --install
- Install Ubuntu.
- Inside Ubuntu:
sudo apt update
sudo apt install -y ansible
Or via pip:
sudo apt install -y python3-pip
pip3 install ansible
- Verify:
ansible --version
🏗 Architecture & Workflow
The workflow is:
- Terraform → triggers Vagrant
- Vagrant → defines & creates the VM (on VirtualBox)
- Ansible → configures the VM (installs Nginx)
- GitHub Actions → automates the entire pipeline
🚦 Step-by-Step Execution
Phase 1: Create VM with Terraform + Vagrant
main.tf
:
terraform {
required_providers {
vagrant = {
source = "bmatcuk/vagrant"
version = ">= 4.0.0"
}
}
required_version = ">= 1.5.0"
}
provider "vagrant" {}
resource "null_resource" "ubuntu_vm" {
provisioner "local-exec" {
command = "vagrant up"
working_dir = "C:/Users/HOUSSAM/Desktop/terraform-ansible-vbox"
}
}
output "vagrant_info" {
value = "Alles gut"
}
Vagrantfile
:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.network "private_network", ip: "192.168.56.10"
config.vm.boot_timeout = 1200
end
Phase 2: Prepare Ansible Inventory
inventory.ini
:
[ubuntu]
127.0.0.1 ansible_port=2222 ansible_user=vagrant ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key
Phase 3: Configure VM with Ansible
playbook.yml
:
- hosts: ubuntu
become: yes
tasks:
- name: Update apt cache
apt: update_cache: yes
- name: Install nginx
apt: name=nginx state=present
- name: Ensure nginx is running
service: name=nginx state=started
Phase 4: Automate with GitHub Actions
Example workflow (.github/workflows/main.yml
):
name: Terraform-Vagrant-Ansible
on:
push:
branches:
- main
workflow_dispatch:
jobs:
terraform:
name: Terraform & Vagrant
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.7
- name: Terraform Init
run: C:Terraformterraform.exe init
- name: Terraform Apply (run Vagrant)
run: C:Terraformterraform.exe apply -auto-approve
- name: Save inventory file
run: |
echo "[ubuntu]" > inventory.ini
echo "127.0.0.1 ansible_user=vagrant ansible_ssh_private_key_file=$HOME/.vagrant.d/insecure_private_key" >> inventory.ini
shell: pwsh
- name: Upload inventory artifact
uses: actions/upload-artifact@v4
with:
name: inventory
path: inventory.ini
ansible:
name: Run Ansible
runs-on: self-hosted
needs: terraform
steps:
- uses: actions/checkout@v3
- name: Download inventory
uses: actions/download-artifact@v4
with:
name: inventory
- name: Fix private key permissions
shell: pwsh
run: |
wsl --user root chmod 600 /mnt/c/Users/HOUSSAM/Desktop/terraform-ansible-vbox/.vagrant/machines/default/virtualbox/private_key
- name: remove the old key li ken ma5doum ken project 9able ken ye5dem
shell: pwsh
run: |
wsl --user root ssh-keygen -f "/root/.ssh/known_hosts" -R "[127.0.0.1]:2222"
- name: Run Playbook
shell: pwsh
run: |
wsl --user root ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i /mnt/c/Users/HOUSSAM/Desktop/terraform-ansible-vbox/inventory.ini /mnt/c/Users/HOUSSAM/Desktop/terraform-ansible-vbox/playbook.yml
âś… Results
- Ubuntu VM provisioned in VirtualBox
-
Nginx installed & running → accessible at
http://192.168.56.10
- End-to-end workflow fully automated via GitHub Actions
- Reproducible setup — no cloud required 🚀
📌 Conclusion
This project shows how IaC concepts can be applied to local infrastructure with the same rigor used in cloud environments.
It’s a great way for DevOps engineers and learners to practice Terraform, Ansible, CI/CD, and automation pipelines without spending on cloud providers.
So , Thank you and I am here to answer your questions.
Houssam Naji