Azure setup: first cloud pass

A first-time Azure run that turned identity and networking into the real curriculum.

Layout

Key takeaways

  • Azure treats identity and networking as the default gatekeepers.
  • Deployment names are part of the API contract, not a label.
  • Tight verification loops beat full app boots when the cloud is new.
  • Free credits are enough to learn the terrain safely.

I went to Azure for a clean, cloud-hosted RAG setup. I expected configuration work. I did not expect the first hour to be a tutorial in identity and network policy. The experience was useful because it forced me to see the platform the way Azure sees it: as a system of locks, not a single machine. If you are new to RAG, start with Retrieval-Augmented Generation in plain terms. For system boundaries and feedback loops, see Systems 001: Foundations. For the difference between tuning and retrieval, see Training vs inference. If context is new, read Context windows as working memory.

If you are new to Azure, start with the free credits so you can explore without pressure: Azure free credits.

Architecture map

Azure makes more sense when you separate where things live from who can touch them.

  • Subscription is the billing boundary.
  • Resource group is your organizational box.
  • Services are the active components: AI Foundry, Postgres, the app host.
  • Identity decides who can act.
  • Networking decides where traffic can flow.
Azure architecture map Subscription and resource group contain services, with identity and networking as control planes. Subscription Resource Group Azure AI Foundry Postgres + pgvector App Host Identity Networking
Subscription and resource group hold the services; identity and networking decide who can do what.
RAG flow on Azure Client to Spring Boot, then to Azure AI Foundry and Postgres with pgvector, with logs on the edge. Client Spring Boot Azure AI Foundry Postgres + pgvector Logs
RAG flow once identity and network gates are aligned.

What happened

I had a Spring Boot backend, a PostgreSQL database with pgvector, and a hosted LLM. The first deployment looked clean, but the system behaved like it was unplugged. The database connection timed out, and the LLM endpoint returned 404s even with the correct API key.

The fix was not in the code. It was in the cloud posture.

The two gates

Identity is the first gate. In Azure AI Foundry, the deployment name is part of the contract. If the app expects gpt-4o and the deployment is named something else, the request fails without a helpful error.

Networking is the second gate. PostgreSQL Flexible Server starts in a default-deny posture. I had to explicitly open the Azure Firewall for my IP and allow internal Azure services.

Identity and networking gates Two panels showing identity and networking checks that block or permit traffic. Identity Networking Deployment name API key + endpoint Firewall rules NSG / VNet
Two locks that decide whether your request is even allowed to speak.

Portal walkthrough

This is the most compact first-time path I found. The goal is to prove the system works before you optimize it. Treat this as a tour of Azure’s main control surfaces.

  1. Create a resource group. This is your container for everything that follows.
  2. Create PostgreSQL Flexible Server. Choose a basic tier. Turn on the pgvector extension after the instance is running.
  3. Open the firewall. Add your current IP and allow Azure services. Without this, connections will fail even if credentials are correct.
  4. Create an Azure AI Foundry project. Deploy a model and give it a deployment name you will use in code.
  5. Collect the endpoint + key. Treat these as the root of your API contract.
Portal path for first runs Five steps from resource group to endpoint and key. Resource Group Postgres Flexible Firewall Rules AI Foundry Deployment Keys
A conceptual map of the portal steps, not tied to UI layout.

First-time config

I kept the first run intentionally small. One model. One database. One backend. Azure gets easier when the first pass is narrow.

Wire the app with explicit environment variables. Avoid hidden defaults for the first pass.

export AZURE_OPENAI_ENDPOINT="https://<resource-name>.openai.azure.com"
export AZURE_OPENAI_API_KEY="<your-key>"
export AZURE_OPENAI_DEPLOYMENT="<deployment-name>"
export DATABASE_URL="postgresql://<user>:<password>@<db-hostname>:5432/<db-name>"
Configuration focus for first runs A minimal set of environment variables grouped by model and database. Model Database endpoint api key deployment host user password
A short list of variables that removes most ambiguity.

Quick checks

Check the database port is reachable:

nc -vz <db-hostname> 5432

Confirm the database allows your connection:

psql "postgresql://<user>:<password>@<db-hostname>:5432/<db-name>"

Verify the model deployment is reachable (Azure OpenAI-style endpoints):

curl -s \
  -H "api-key: $AZURE_OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  "$AZURE_OPENAI_ENDPOINT/openai/deployments/$AZURE_OPENAI_DEPLOYMENT/chat/completions?api-version=2024-06-01" \
  -d '{"messages":[{"role":"user","content":"ping"}],"max_tokens":5}'

Failure modes

  • The deployment name in code does not match the Azure AI Foundry deployment name.
  • The database firewall blocks your IP, even if credentials are correct.
  • The endpoint URL is right but the API version is not supported.
  • Secrets are scattered across files and the app reads the wrong one.

What made the difference

I mirrored the deployment name in my app config so there was no drift between code and Azure AI Foundry. I treated firewall setup as a prerequisite, not a later fix. And I validated the model endpoint with curl before touching Spring Boot.

What I would do next time

I would open networking first, even before spinning up the app. I would validate the model endpoint and database with CLI probes to keep feedback tight. And I would centralize deployment names and resource groups from day one, because config drift hides the real problem.