Documentation
adrs/044-postgresql-public-access.md
ADR-044: PostgreSQL Public Access (Non-VNet Integration)
Status
Accepted
Context
When deploying Azure PostgreSQL Flexible Server to Azure, there are two networking options:
- Public Access - Server has a public endpoint, access controlled via firewall rules
- Private Access (VNet Integration) - Server is deployed into a VNet subnet with no public endpoint
During initial Azure deployment attempts, we encountered persistent failures when deploying PostgreSQL Flexible Server with VNet integration. Investigation revealed the root cause:
VNet Integration Requirements
PostgreSQL Flexible Server with VNet integration requires:
- Dedicated Subnet: A subnet delegated exclusively to
Microsoft.DBforPostgreSQL/flexibleServers - NSG Rules: Network Security Group rules allowing outbound traffic to:
AzureActiveDirectoryservice tag (for Entra ID authentication)Storageservice tag (for WAL file archival)
- Route Table Configuration: If using custom routes, rules for
AzureActiveDirectorywithInternetnext hop
The Problem
Our deployment was failing because:
- PostgreSQL 18 Preview: We use PG 18 for UUID v7 native support, but PG 18 Preview does not support Entra ID authentication
- Password Authentication: We're using password auth, which doesn't benefit from VNet's Entra ID integration
- NSG Complexity: The Container Apps subnet didn't have the required outbound rules for
AzureActiveDirectory - Subnet Delegation Conflict: PostgreSQL requires its own dedicated subnet (can't share with Container Apps)
The error manifested as the PostgreSQL server getting stuck in a failed provisioning state, unable to complete deployment due to blocked outbound connectivity to Azure Active Directory services.
Decision
Deploy PostgreSQL Flexible Server with public access instead of VNet integration, using firewall rules to restrict access to Azure services only.
Implementation
// In DynaplexInfrastructureExtensions.cs
var allowAzureServices = new PostgreSqlFlexibleServerFirewallRule("allowAzureServices") {
Parent = server,
Name = "AllowAllAzureServices",
StartIPAddress = System.Net.IPAddress.Parse("0.0.0.0"),
EndIPAddress = System.Net.IPAddress.Parse("0.0.0.0")
};
infra.Add(allowAzureServices);
The 0.0.0.0 to 0.0.0.0 range is Azure's special notation for "allow all Azure services" - it permits connections from any IP address allocated to Azure services, including our Container Apps.
Consequences
Positive
- Simplified Deployment: No need to manage dedicated PostgreSQL subnet, NSG rules, or route tables
- Faster Iteration: Removes a complex failure point during infrastructure provisioning
- Container Apps Connectivity: Container Apps connect via public endpoint without VNet peering
- Consistent with Auth Model: Password authentication doesn't benefit from VNet's Entra ID features anyway
Negative
- Public Endpoint: Server has a public DNS name (though firewalled to Azure services only)
- Broader Access: The
AllowAllAzureServicesrule permits any Azure service (including other customers' services) - mitigated by password authentication requirement - Not Zero-Trust: Traffic traverses public internet rather than private network backbone
Security Mitigations
- Password Authentication: Connections still require valid PostgreSQL credentials
- TLS Required: All connections use TLS encryption
- Azure-Only Access: Firewall blocks all non-Azure IP addresses
- Connection String Secrets: Credentials managed via Aspire secrets, not exposed in configuration
Future Migration Path
When PostgreSQL 18 reaches GA with Entra ID support:
- Create dedicated PostgreSQL subnet with proper delegation
- Configure NSG with outbound rules for
AzureActiveDirectoryandStorageservice tags - Enable Entra ID authentication on the server
- Update Container Apps to use managed identity for database access
- Switch server to private access mode
- Remove public endpoint and firewall rules
This migration can be done with minimal downtime using Azure's networking change capabilities.
References
- PostgreSQL VNet Integration Requirements
- PostgreSQL Firewall Rules
- Entra ID Authentication Prerequisites
- ADR-043: Azure Infrastructure Architecture (VNet for Container Apps)