DEV Community

Humza Inam
Humza Inam

Posted on

Learning Azure Networking Through Code: My Spring Boot + Terraform Journey

Building a production-style network from scratch to understand how the cloud really works


What I Built

I created a complete Azure network infrastructure with multiple virtual networks, security rules, load balancing, and a Spring Boot application to test it all. Think of it as building a miniature version of how companies actually structure their cloud networks, but small enough to learn from and cheap enough to run on Azure's student credits.

The Setup

Two separate virtual networks connected through VNet peering, with a Spring Boot REST API that provides real-time network diagnostics. An Application Gateway acts as the public entry point, routing traffic to a private VM that can only be accessed through specific security rules. There's also a bastion host for secure SSH access and private endpoints connecting to Azure Storage without touching the public internet.

The flow: Internet → Application Gateway → Private Spring Boot VM → Storage Account (via private endpoint)

Why This Stack?

The combination seems unusual at first: Terraform for infrastructure, Spring Boot for the application, and Azure networking concepts all mixed together. But that's exactly why I chose it. I wanted to learn Spring Boot (Java web development) while also understanding networking fundamentals. By building the network infrastructure myself and then deploying an app that could test and report on that infrastructure, I learned both topics simultaneously.


Getting Started with Azure Student Credits

This entire project runs on Azure's free student tier. No credit card needed, and you get $100 in credits renewed annually. The resources I used (small VMs, basic networking) cost pennies per hour, so you can run this for days while learning.

How to get started:

  1. Go to azure.microsoft.com/free/students
  2. Verify with your student email
  3. Get instant access to enterprise-grade cloud tools

The key insight I learned: don't just rely on your university's resources. External companies like Microsoft, AWS, and Google actively want students learning their platforms. Take advantage of these programs.


The Architecture

Two Virtual Networks (VNets)

I created two separate networks:

  • Primary VNet (10.0.0.0/16): Contains the Spring Boot application, bastion host, and Application Gateway
  • Secondary VNet (10.1.0.0/16): A separate network for testing cross-network communication

These VNets are connected through VNet peering, which lets them communicate privately without going through the public internet.

Five Subnets for Segmentation

Primary VNet:

  • Public subnet (10.0.1.0/24) - Bastion host
  • Private subnet (10.0.2.0/24) - Spring Boot app and private endpoint
  • App Gateway subnet (10.0.3.0/24) - Load balancer

Secondary VNet:

  • Public subnet (10.1.1.0/24) - Reserved
  • Private subnet (10.1.2.0/24) - Test VM running Nginx

Subnets let you isolate different types of resources and apply different security rules to each.

Security Through Network Security Groups (NSGs)

Each subnet has an NSG acting as a firewall. For example, the private subnet only allows:

  • SSH from the public subnet (bastion host)
  • HTTP traffic on port 8080 from within the VNet
  • Traffic from the App Gateway subnet
  • Communication with the secondary VNet

Everything else is blocked by default. This is zero-trust networking - nothing is allowed unless explicitly permitted.

The Bastion Pattern

The bastion host is a VM with a public IP that acts as a secure jump box. You SSH into the bastion first, then from there you can access private VMs. This means your application servers never need public IPs, reducing attack surface.

ssh azureuser@bastion-ip
# Then from bastion:
ssh azureuser@private-vm-ip
Enter fullscreen mode Exit fullscreen mode

Application Gateway for Public Access

The Application Gateway is Azure's Layer 7 load balancer. It has a public IP and routes incoming HTTP requests to the private Spring Boot VM on port 8080. It includes:

  • Health probes that check /health every 30 seconds
  • Automatic routing rules
  • Protection for the backend (the private VM stays private)

Private Endpoints for Secure Storage Access

The coolest part: the private VM connects to Azure Storage without using the public internet. A private endpoint creates a network interface in your VNet that maps to the storage account. When the VM resolves storageaccount.blob.core.windows.net, it gets a private IP (10.x.x.x) instead of a public one.

This is achieved through:

  1. Private DNS zone for privatelink.blob.core.windows.net
  2. Private endpoint in the private subnet
  3. DNS resolution that returns private IPs

NAT Gateway for Outbound Internet

Private VMs need internet access for things like software updates. The NAT Gateway provides a single public IP that all private subnet resources share for outbound connections. This way, they can reach the internet but the internet can't reach them.


The Spring Boot Application

I built a REST API with several diagnostic endpoints to test the network:

GET /health - Basic health check for the Application Gateway probe

{
  "status": "UP",
  "timestamp": 1234567890,
  "message": "Hello from Azure Private VM!",
  "storage_account": "demostorageXXXX"
}
Enter fullscreen mode Exit fullscreen mode

GET /api/vm-info - Reports the VM's network details

{
  "hostname": "vm-private-demo",
  "private_ip": "10.0.2.4",
  "vnet": "vnet-demo",
  "resource_group": "rg-demo-networking"
}
Enter fullscreen mode Exit fullscreen mode

GET /api/network-test - Tests DNS resolution of the storage account

{
  "storage_fqdn": "demostorage.blob.core.windows.net",
  "resolved_ip": "10.0.2.5",
  "dns_resolution": "SUCCESS",
  "using_private_endpoint": true
}
Enter fullscreen mode Exit fullscreen mode

GET /api/storage-test - Validates private endpoint connectivity

Why Spring Boot?

I wanted to learn Java web development while building this infrastructure project. Spring Boot makes it easy to create REST APIs with minimal boilerplate. The @RestController and @GetMapping annotations handle all the HTTP routing automatically.

The application runs as a systemd service on Ubuntu, managed through a bash setup script that:

  1. Installs Java and Maven
  2. Creates the Spring Boot project structure
  3. Builds the JAR file with Maven
  4. Configures a systemd service for automatic startup
  5. Creates test scripts for network validation

Infrastructure as Code with Terraform

All 700+ lines of infrastructure are defined in code. This means I can destroy everything and rebuild it identically in minutes. Here's how Terraform structures the resources:

Resource Dependencies

Terraform automatically figures out what order to create resources based on dependencies. For example:

  • VNet must exist before subnets
  • Subnets must exist before VMs
  • NSGs must exist before NSG associations
  • Private DNS zone must be linked to VNet before private endpoint

Templating in Cloud-Init Scripts

The Spring Boot setup script uses Terraform's templatefile() function to inject variables:

custom_data = base64encode(templatefile("spring-boot-setup.sh", {
  storage_account_name = azurerm_storage_account.demo.name
  container_name       = azurerm_storage_container.demo.name
  vnet_name           = azurerm_virtual_network.main.name
}))
Enter fullscreen mode Exit fullscreen mode

This lets the Java application know which storage account to test against without hardcoding values.


What I Learned

Networking Fundamentals

Before this project, concepts like subnets, CIDR notation, and routing tables were abstract. Now I understand:

  • Why subnets matter: They isolate resources and let you apply different security policies
  • How DNS resolution works: Especially with private DNS zones overriding public DNS
  • The difference between Layer 4 and Layer 7 load balancing: NAT Gateway vs Application Gateway
  • Network security groups vs firewalls: NSGs filter traffic at the subnet/NIC level

Spring Boot Development

I learned how to:

  • Structure a Spring Boot project with Maven
  • Create REST controllers with proper HTTP methods
  • Handle JSON serialization automatically
  • Deploy Java applications as Linux services
  • Build projects in CI/CD-style automation scripts

Azure Cloud Services

Working with Azure taught me:

  • How VNet peering enables private cross-network communication
  • Private endpoints eliminate public internet exposure for PaaS services
  • Application Gateway health probes and backend pools
  • Service endpoints vs private endpoints

Infrastructure as Code Best Practices

I learned to:

  • Use variables and outputs effectively
  • Structure Terraform for readability
  • Handle dependencies and resource ordering
  • Inject configuration into VMs via cloud-init
  • Manage SSH keys securely

Challenges I Faced

Maven Build Issues

The cloud-init script had to handle different Java versions and ensure the JAR file path was correctly detected. I added fallback logic to find any built JAR file instead of hardcoding the name.

Application Gateway Health Probes

Initially, the health probe kept failing because I forgot to configure the probe path to match the /health endpoint. The gateway needs explicit configuration for backend health checks.

Private DNS Resolution

Understanding when to use service endpoints vs private endpoints took time. Service endpoints secure the service but still use public IPs. Private endpoints actually inject a private IP into your VNet, which is more secure but requires private DNS zones.

Network Security Group Rules

Getting the NSG priorities and port ranges right required iteration. I learned to be explicit with source and destination address prefixes rather than using wildcards.


Final Thoughts

This project taught me that the best way to learn cloud networking is to build something real. Reading documentation helps, but nothing compares to troubleshooting why your private endpoint DNS isn't resolving or why the Application Gateway can't reach your backend.

Combining Spring Boot with networking infrastructure might seem unusual, but it forced me to understand both topics deeply. The application wasn't just sitting on top of the network - it was actively testing and reporting on network behavior.

Azure's student credits made this possible without any financial barrier. If you're a student interested in cloud infrastructure, networking, or backend development, I encourage you to build something similar. Start small, break things, fix them, and learn through doing.


About This Post

This blog post was written based on the project's Terraform configuration, Spring Boot setup scripts, and my personal reflections throughout the learning process. The narrative was structured and refined with AI assistance to create a clear and approachable explanation of the technical implementation.

Top comments (0)