An Infrastructure as Code (IaC) project using Terraform to provision a security-hardened Linux web hosting environment in Microsoft Azure. This project demonstrates secure cloud infrastructure practices aligned with NIST 800-171 control families, with an emphasis on access control, network segmentation, and compliance-ready resource governance.
This configuration deploys the following resources within a single Azure resource group:
- Virtual Network with a
10.0.0.0/16address space, providing network isolation for all compute resources - Subnet (
10.0.2.0/24) for internal workloads, segmented from the broader VNet - Network Security Group (NSG) restricting inbound SSH (port 22) to a single whitelisted IP address, associated at the subnet level
- Linux Virtual Machine (Ubuntu 22.04 LTS) using SSH key-based authentication — password authentication is disabled
- Public IP for remote administration, scoped behind NSG rules
- Network Interface bridging the VM to the internal subnet with the public IP attached
┌─────────────────────────────────────────────────────┐
│ Azure Resource Group │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ Virtual Network (10.0.0.0/16) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Subnet: internal (10.0.2.0/24) │ │ │
│ │ │ ┌──────────┐ ┌───────────────────┐ │ │ │
│ │ │ │ NSG │───▶│ Network Interface │ │ │ │
│ │ │ │ SSH only │ │ ┌─────────────┐ │ │ │ │
│ │ │ │ (1 IP) │ │ │ Linux VM │ │ │ │ │
│ │ │ └──────────┘ │ │ Ubuntu LTS │ │ │ │ │
│ │ │ │ └─────────────┘ │ │ │ │
│ │ │ └───────────────────┘ │ │ │
│ │ └──────────────────────────┬──────────────┘ │ │
│ │ │ │ │
│ └─────────────────────────────┼─────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ Public IP │ │
│ │ (Static) │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────┘
This project applies several security practices relevant to regulated and compliance-driven environments:
- SSH is the sole remote access method; password-based authentication is disabled
- The NSG restricts inbound SSH to a single authorized IP address, reducing the attack surface to a known endpoint
- All other inbound traffic is denied by default via Azure NSG implicit deny rules
- Workloads are isolated within a dedicated VNet and subnet
- The NSG is associated at the subnet level, enforcing consistent security policy across all resources within the subnet rather than per-NIC, which reduces configuration drift
- SSH key-based authentication is enforced; no shared or static passwords
- Admin access is limited to a single named account
All resources are tagged with compliance metadata to support automated policy enforcement and audit readiness:
| Tag | Purpose |
|---|---|
environment |
Identifies the deployment stage (dev, staging, prod) |
project |
Groups resources by project for cost tracking and ownership |
data_classification |
Enables Azure Policy rules based on data sensitivity (e.g., CUI, public) |
compliance_framework |
Maps resources to applicable regulatory frameworks (e.g., NIST-800-171) |
managed_by |
Indicates the provisioning method for change control audits |
owner |
Identifies the responsible party for incident response |
In a production environment, Azure Policy definitions could enforce that resources without required tags (such as data_classification) are denied at deployment time.
- Terraform >= 1.0 (or OpenTofu)
- Azure CLI authenticated (
az login) - An Azure subscription with an active resource provider for
Microsoft.Compute - An SSH key pair (the config expects
~/.ssh/azure.pub)
-
Clone the repository:
git clone git@github.com:mdyoung3/azure_symfony.git cd azuresymfony -
Create your variable overrides:
touch terraform.tfvars
Edit
terraform.tfvarswith your values:project_name = "azure_website_environment" ip_address = "YOUR_PUBLIC_IP/32"
-
Initialize and plan:
terraform init terraform plan
-
Apply:
terraform apply
-
Connect to the VM:
ssh adminuser@$(terraform output -raw public_ip) -
Tear down when finished:
terraform destroy
- Azure Key Vault for centralized secrets management, replacing local SSH key references
- Log Analytics Workspace with VM diagnostic settings for centralized logging and monitoring, supporting incident response and audit evidence collection
- Managed Identity (Entra ID) assigned to the VM to eliminate static credentials for Azure service access
- Remote state backend using Azure Storage with state locking to support team-based workflows
- CI/CD pipeline (GitHub Actions) running
terraform fmt,terraform validate, andterraform planon pull requests - Modularized structure separating networking, compute, and security into reusable modules
- Terraform — Infrastructure as Code
- Microsoft Azure — Cloud platform (Resource Groups, VNets, NSGs, Linux VMs)
- Ubuntu 22.04 LTS — Server operating system
- Cloud-init — VM bootstrapping and provisioning