Skip to content

Repository files navigation

azure-iac-lab

Deployment of a basic Azure architecture, done first manually (portal/CLI, AZ-104 mindset) then reproduced in Terraform (Infrastructure as Code) — in the same repo, to demonstrate both skill sets.

Architecture Deployed


┌─────────────────────────────┐
                    │      Resource Group          │
                    │                              │
                    │  ┌────────────────────────┐  │
                    │  │        VNet 10.0.0.0/16 │  │
                    │  │  ┌──────────────────┐   │  │
                    │  │  │ Subnet 10.0.1.0/24│  │  │
                    │  │  │                    │  │  │
                    │  │  │   ┌────────────┐   │  │  │
    Internet ───────┼──┼──┼──▶│  Linux VM  │   │  │  │
    (SSH:22,        │  │  │   │ (Ubuntu    │   │  │  │
    HTTP:80)         │  │  │   │  22.04)    │   │  │  │
                    │  │  │   └────────────┘   │  │  │
                    │  │  │        ▲            │  │  │
                    │  │  │       NSG            │  │  │
                    │  │  │  (SSH + HTTP rules)  │  │  │
                    │  │  └──────────────────┘   │  │
                    │  └────────────────────────┘  │
                    │                              │
                    │  ┌────────────────────────┐  │
                    │  │     Storage Account       │  │
                    │  └────────────────────────┘  │
                    └─────────────────────────────┘

Repository Structure


azure-iac-lab/
├── MANUAL_SETUP.md # Documented manual deployment (portal/CLI)
├── main.tf # Azure resources (Terraform)
├── variables.tf # Configurable variables
├── outputs.tf # Outputs (public IP, names, etc.)
├── terraform.tfvars.example # Example values to copy into terraform.tfvars
├── .gitignore # Excludes tfstate, real tfvars, SSH key
└── .github/workflows/terraform.yml # CI: terraform plan on every PR

Prerequisites

  • An Azure account (free tier or Azure for Students is sufficient)
  • Terraform ≥ 1.5: terraform -v
  • Azure CLI: az login

Manual Deployment

See MANUAL_SETUP.md for the full detail (real commands, errors encountered, time spent).

Terraform Deployment

# 1. Azure authentication
az login

# 2. Copy and adapt variables
cp terraform.tfvars.example terraform.tfvars
# → edit allowed_ssh_source with your real public IP!

# 3. Initialize
terraform init

# 4. Preview changes
terraform plan

# 5. Apply
terraform apply

# 6. Retrieve the VM's public IP
terraform output vm_public_ip

# 7. Connect via SSH
terraform output -raw ssh_connection_command

# 8. Destroy the infrastructure once done (avoids unnecessary costs)
terraform destroy

Manual vs Terraform — Lessons Learned

Criterion Manual (portal/CLI) Terraform
Deployment time ~1h (including region + SKU capacity debugging) ~1min30 (a single terraform apply command)
Teardown time A few seconds (az group delete --no-wait, asynchronous, no visible confirmation) ~2 min (terraform destroy, sequential, with confirmation for each resource)
Number of commands ~10 distinct commands to type and chain 1 command (terraform apply)
Errors encountered Region policy (RequestDisallowedByAzure) + SKU capacity unavailable (SkuNotAvailable), debugged manually one by one 0 errors — the correct configuration (region + VM size) was directly baked into variables.tf thanks to lessons learned during the manual run
Reproducibility Low — depends on the operator's memory and rigor Total — the same result is guaranteed on every run
Infrastructure documentation Manual, written separately (MANUAL_SETUP.md) The code (main.tf) is the documentation
Cleanup / teardown Manual, dependency order must be handled by hand terraform destroy automatically handles the dependency/deletion order
Scaling (e.g. 10 VMs) Repetitive, error-prone with each repetition A single count or for_each variable, no extra effort

The most notable finding: both errors encountered manually (Azure for Students region policy restricted to swedencentral, and SkuNotAvailable capacity errors across several VM sizes before finding Standard_B2ats_v2) would have been just as blocking with Terraform — but once understood and fixed once in variables.tf, they never resurface. The manual approach requires remembering the fix on every future attempt; Terraform encodes it permanently.

Security Notes

  • The SSH rule defaults to * in the examples: restrict it to your own IP in practice (terraform.tfvars).
  • The SSH private key is generated automatically by Terraform (*.pem) and excluded from the repo via .gitignore.
  • Never commit terraform.tfvars if it contains sensitive values, nor *.tfstate files (they may contain plaintext secrets).

CI/CD

Every Pull Request automatically triggers terraform fmt, terraform validate, and terraform plan, with the result posted as a comment on the PR (see .github/workflows/terraform.yml).

GitHub Actions secrets to configure (Settings > Secrets and variables > Actions): AZURE_CREDENTIALS, ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_SUBSCRIPTION_ID, ARM_TENANT_ID (created via a Service Principal: az ad sp create-for-rbac --sdk-auth).

Author

Hiba bensaid — Data Science & Computer Science Engineering Student | Cloud & Automation Enthusiast

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages