On November 20, 2024, AWS announced VPC Origins. This new feature enables the use of CloudFront with applications hosted in private subnets, either through a load balancer (ALB or NLB) or EC2 instances.
This excellent news was very well received, as user requests passing through CloudFront to AWS applications or services no longer needed to be exposed to the public internet. Additionally, it optimizes security management and facilitates the use of CloudFront as a single entry point for applications.
While the primary use of VPC Origins is to establish private and secure communication with applications behind an ELB, such as ECS/EKS clusters or EC2 instances, we can leverage this new resource and go beyond the recommended usage.
Private API Gateway Integration
A key advantage of VPC Origins is establishing communication between CloudFront and a Private Endpoint of Amazon API Gateway REST type. The most well-known options are between CloudFront and a Regional or Edge API Gateway Endpoint, but additional security elements need to be applied for it to work correctly.
I have observed that the Edge API Gateway offers better global latencies (5-12ms), but the Private API Gateway with VPC Origins wins on security due to improved isolation. However, this solution has a 7 times higher cost and significantly higher operational complexity (CF, ALB, VPC Endpoint, API Gateway). The decision depends on whether your use case requires critical enterprise systems or global public applications where latency is a top priority concern.
Recommended Use Cases
- Critical enterprise systems where security is prioritized over latency.
- Internal applications that require complete isolation from the public network.
- Multi-account architectures that require centralized access through CloudFront.
Technical Implementation Considerations
Currently, the only way to establish this private communication is by adding the "x-apigw-api-id" header to the CloudFront origin configuration and using VPC Origins, an ALB, a VPC Endpoint, and the private Default Endpoint of an API Gateway.
But why can't I use the private Custom Domain Name that API Gateway provides? For two reasons: AWS doesn't allow us to modify the "Host" header in CloudFront's origin configuration, and VPC Origins doesn't support header rewriting with Lambda@Edge. To use the private Custom Domain Name, we need to send the "Host" header in the request. Due to the limitations of CloudFront and VPC Origins, we can only use the private Default Endpoint.
There are some essential details I must mention for the implementation to work:
- We must use an ALB. Why not an NLB? There are three main reasons. First, we must establish communication with the HTTPS protocol from the ALB to the VPC Endpoint. VPC Origins allows establishing HTTP communication to the ALB; however, we can't use this protocol because the ALB will attempt to maintain the same protocol and send the request to the Endpoint, resulting in a failed response. Second, when you configure VPC Origins with HTTPS, the load balancer requires a certificate. Currently, VPC Origins doesn't support an NLB with TLS, and in TCP passthrough, the NLB can't present one. However, we can configure the listener port number as desired; it doesn't have to be 443 (default for HTTPS). The third reason is that with an ALB, we can leverage forwarding rules to redirect to different target groups in case of more complex architectures.
- The ALB must have a certificate signed by a trusted certificate authority, such as GlobalSign, DigiCert, or Symantec. The reason we can't use a self-signed certificate is that CloudFront, when communicating via HTTPS with its origin, verifies that a trusted certificate authority has issued the certificate. If the origin (ALB) returns an expired, invalid, or self-signed certificate, CloudFront interrupts the TCP connection and returns HTTP status code 502.
- The ALB must be created in the same account as the CloudFront distribution. Currently, AWS doesn't allow creating the ALB in another account.
- The target group must be of the IP type with the Health Check protocol set to HTTPS and the Success codes set to 403 when pointing to the root path (/).
- Security group configuration. When a VPC Origins is created for the first time, a security group called "CloudFront-VPCOrigins-Service-SG" is created simultaneously. You must allow the security group created by VPC Origins to be included in the load balancer's security group.
Implemented Architectures
Architecture 1: Single-Account Deployment
This basic architecture encompasses all components deployed within a single AWS account, making it ideal for simple use cases or development environments.
Architecture 2: Two or more Environments with Multi-Account Deployment
In this configuration, we use one VPC Origins and one ALB to serve applications in two different environments, distributed across multiple AWS accounts. For this architecture to work and route traffic to various target groups, rules must be created in the ALB, using the "Host" header with the hostname of each CloudFront as the value.
Architecture 3: Multi-Application Architecture
The most complex architecture includes multiple applications in two or more environments, with numerous CloudFronts, VPC Origins, ALBs, and across multiple AWS accounts. For this case, we must create some origins (one per application) and establish the corresponding behaviors that match each application/origin.
Practical Implementation
This guide will walk you through the step-by-step process of implementing VPC Origins with a private API Gateway using the AWS console.
Step 1: Verify base infrastructure
Objective: Validate that you have the necessary network infrastructure.
Actions:
- Access the VPC console.
- Verify that you have at least two private subnets in different AZs. While it's technically possible to create the ALB in public subnets, to maintain completely private communication, it's recommended to deploy it in private subnets.
Step 2: Create a VPC Endpoint for API Gateway
Objective: Establish private connectivity to the API Gateway.
Actions:
- Go to VPC → Endpoints → Create Endpoint
- Configure the following parameters:
- Service category: AWS services
- Service name: com.amazonaws.[region].execute-api
- VPC: Select your VPC
- Subnets: Select private subnets
- Security groups: Create a new one temporarily
- Inbound: HTTPS (443) from the ALB's security group or subnets. If they're in different accounts, I recommend adding the CIDR blocks of the private subnets where the ALB is located. I don't recommend adding only IP addresses because they can change over time.
- Outbound: All traffic
Step 3: Create a private API Gateway
Objective: Configure the API Gateway that will receive requests.
Actions:
- Go to API Gateway → Create API → REST API Private
- Configure:
- API name: your-private-api
- Endpoint type: Private
- VPC endpoints: Select the VPC endpoint created in the previous step
- Configure Resource Policy
- Deploy to a stage (e.g., /dev)
- Enable logs (Errors and Info)
Step 4: Create Target Group
Objective: Configure the target group that will connect the ALB with the VPC Endpoint.
Actions:
- Go to EC2 → Target Groups → Create target group
- Configure:
- Target type: IP addresses
- Protocol: HTTPS
- Port: 443
- VPC: Your VPC
- Health check protocol: HTTPS
- Health check path: /
- Success codes: 403
- In Register targets, add the VPC Endpoint IPs:
- Go to VPC → Endpoints → [your-endpoint] → Network interfaces
- Copy the private IPs and add them as targets
Step 5: Create Application Load Balancer
Objective: Configure the ALB that will act as a "proxy" to the VPC Endpoint.
Actions:
- Go to EC2 → Load Balancers → Create load balancer → Application Load Balancer.
- Basic configuration:
- Scheme: Internal
- IP address type: IPv4
- VPC: Your VPC
- Subnets: Select private subnets (minimum 2 AZs)
- Security groups: Create a new one:
- Inbound: HTTPS (443). Temporarily add the CloudFront managed prefix list "com.amazonaws.global.cloudfront.origin-facing". This rule will be changed later once the VPC Origins is created.
- Outbound: All traffic
- Listener: HTTPS:443
- SSL certificate: Select your valid certificate
- Default action: Forward to target group (created in step 4)
Validation: Wait for the ALB to be "Active" and the target group to be "Healthy".
Step 6: Create VPC Origin
Objective: Establish the connection between CloudFront and your VPC.
Actions:
- Go to CloudFront → VPC origins → Create VPC origin
- Configure:
- Origin domain: ARN of the ALB created in the previous step
- Protocol: HTTPS only
- Port: 443
Validation: The VPC Origin should display a "Deployed" status within 5–10 minutes.
Step 7: Update ALB's Security Groups
Objective: Allow communication between CloudFront and the ALB.
Actions:
- Go to EC2 → Security Groups
- Edit the ALB's security group:
- Inbound rules: Modify the previously created rule and add the source "CloudFront-VPCOrigins-Service-SG"
Step 8: Create CloudFront distribution
Objective: Configure CloudFront to use the VPC Origin.
Actions:
- Go to CloudFront → Create distribution
- Origin settings:
- Origin domain: Select your VPC origin
- Protocol: HTTPS only
- Custom headers: Add
- Header name: "x-apigw-api-id"
- Value: [API-ID from step 3]
- Origin path: /dev (or your stage)
- Default cache behavior:
- Viewer protocol policy: HTTPS only
- Cache policy: Managed-CachingDisabled (for testing)
- Origin request policy: If you're going to implement Architecture 2, add the Managed-AllViewer policy so you can capture the hostname in ALB rules.
Settings:
- Alternate domain name (CNAME): your-domain.com (optional)
- SSL certificate: Use ACM certificate if you have a CNAME
Step 9: Testing and validation
Objective: Verify that the entire integration works correctly.
Basic connectivity test:
- curl -v https://[cloudfront-domain]/[your-resource]
- Expected result:
- Response data from your API
- "x-amz-apigw-id" header in the response
- No 502 or 503 errors
- Verify API Gateway logs:
- Go to CloudWatch → Log groups → API-Gateway-Execution-Logs_[api-gateway-ID]/[stage]
- Look for the "x-apigw-api-id" header in the logs
- Confirm that requests are coming from CloudFront
I hope this article is of great help to you. Best regards, and I look forward to seeing you next time. Thank you!
Top comments (0)