A robust, scalable, and secure Azure environment built for developers.
Nginx is successfully installed and running!
Secure, governed, and pre-provisioned environments so you can start building applications immediately without worrying about foundational setup.
A centralized network architecture that provides efficient traffic management, shared services, and enhanced security across all environments.
Isolated Development and Production spokes ensure stability and security. Deploy with confidence, knowing your critical workloads are protected.
Our entire cloud environment is defined and managed through code.
At UPT, we don't build servers, we write code that builds them. By defining our infrastructure—networks, VMs, databases, and policies—in code, we achieve unparalleled consistency, repeatability, and auditability. Every change is version-controlled in Git, peer-reviewed, and deployed through automated pipelines, minimizing human error and maximizing velocity.
This approach empowers developers by providing stable, predictable environments while ensuring security and governance are baked in from the start.
We use HashiCorp Terraform to provision all foundational resources in Azure. This includes the Landing Zone scaffolding, Virtual Networks (Hub & Spokes), Storage Accounts, and Azure Kubernetes Service (AKS) clusters. Terraform's declarative syntax allows us to define the desired state of our infrastructure, and it intelligently handles the creation, update, or destruction of resources to match that state.
# main.tf - Defines a resource group for dev resources
resource "azurerm_resource_group" "dev_rg" {
name = "upt-dev-resources-rg"
location = "West Europe"
tags = {
environment = "Development"
managed_by = "Terraform"
}
}
Once infrastructure is provisioned by Terraform, we use Ansible for configuration management. Ansible automates tasks like installing software (e.g., Nginx, monitoring agents), applying security hardening policies, and managing application configurations on our virtual machines. Its agentless architecture and simple YAML syntax make it fast and easy to manage fleets of servers consistently.
- name: Install and start Nginx
hosts: webservers
become: yes
tasks:
- name: Install nginx package
apt:
name: nginx
state: latest
update_cache: yes
- name: Start nginx service
service:
name: nginx
state: started
enabled: yes
To ensure our Virtual Machines are secure and consistent, we use HashiCorp Packer to build "golden images". Packer takes a base OS image, runs provisioning scripts (like Ansible playbooks or shell scripts) to install necessary software and apply security patches, and then saves it as a custom image in Azure Compute Gallery. New VMs are then deployed from this pre-configured, hardened image, dramatically reducing boot times and configuration drift.
{
"builders": [{
"type": "azure-arm",
"client_id": "{{env `AZURE_CLIENT_ID`}}",
"subscription_id": "{{env `AZURE_SUBSCRIPTION_ID`}}",
"os_type": "Linux",
"image_publisher": "Canonical",
"image_offer": "UbuntuServer",
"image_sku": "18.04-LTS",
...
}],
"provisioners": [{
"type": "ansible",
"playbook_file": "./playbooks/base-setup.yml"
}]
}
All IaC changes are managed through a Git-centric workflow using Azure DevOps Pipelines. When a developer submits a pull request with Terraform or Ansible changes, the pipeline automatically runs linting, validation, and a "plan" stage to preview the impact. Once approved and merged, the pipeline applies the changes to the target environment. This ensures every infrastructure modification is tested, reviewed, and auditable.
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformInstaller@0
inputs:
terraformVersion: 'latest'
- task: TerraformCLI@0
displayName: 'terraform init'
inputs:
command: 'init'
# ... backend config
- task: TerraformCLI@0
displayName: 'terraform apply'
inputs:
command: 'apply'
environmentServiceName: 'Azure-SPN-Prod'
commandOptions: '-auto-approve'
Quick access to tools, service status, and resources.
# Login to Azure
az login --tenant yourtenant.onmicrosoft.com
# Set subscription
az account set --subscription "UPT-DEV-SUBSCRIPTION"
# Get storage account key
az storage account keys list -g "upt-dev-rg" -n "uptdevstorage" --query "[0].value" -o tsv
# Connect to a production Linux VM
ssh your-user@upt-prod-vm-01.westeurope.cloudapp.azure.com