This guide describes the three deployment modes available for MCP Gateway Registry on AWS ECS.
| Scenario | Recommended Mode | enable_cloudfront |
enable_route53_dns |
|---|---|---|---|
| Custom domain with Route53/ACM | Custom Domain | false |
true |
| HTTPS without custom domain | CloudFront | true |
false |
| Local development/testing | Development | false |
false |
| Both access paths needed | Dual Ingress | true |
true |
The deployment_mode output indicates the active configuration:
| Mode | enable_cloudfront |
enable_route53_dns |
Output Value |
|---|---|---|---|
| CloudFront | true |
false |
cloudfront |
| Custom Domain | false |
true |
custom-domain |
| Dual Ingress | true |
true |
custom-domain |
| Development | false |
false |
development |
Note: Dual Ingress reports as
custom-domainsince Route53 DNS is the primary access path.
flowchart TB
subgraph "Custom Domain Mode"
U1[Users] -->|HTTPS| R53[Route53 DNS]
R53 --> ACM1[ACM Certificate]
ACM1 --> ALB1[ALB with HTTPS]
ALB1 --> ECS1[ECS Services]
end
subgraph "CloudFront Mode"
U2[Users] -->|HTTPS| CF[CloudFront]
CF -->|HTTP + Custom Header| ALB2[ALB]
ALB2 --> ECS2[ECS Services]
end
subgraph "Development Mode"
U3[Users] -->|HTTP| ALB3[ALB DNS]
ALB3 --> ECS3[ECS Services]
end
Use when: You have a Route53 hosted zone and want custom domain URLs.
Configuration:
enable_cloudfront = false
enable_route53_dns = true
base_domain = "mycorp.click"URLs:
- Registry:
https://registry.us-west-2.mycorp.click - Keycloak:
https://kc.us-west-2.mycorp.click
Features:
- ACM certificates for HTTPS
- Custom domain names
- Route53 DNS records
Use when: You need HTTPS but don't have a custom domain or Route53 hosted zone. Ideal for workshops, demos, evaluations, or any deployment where custom DNS isn't available.
Configuration:
enable_cloudfront = true
enable_route53_dns = falseURLs:
- Registry:
https://d1234abcd.cloudfront.net - Keycloak:
https://d5678efgh.cloudfront.net
Features:
- Default CloudFront certificates (
*.cloudfront.net) - No custom domain required
- HTTPS via CloudFront TLS termination
- Custom
X-Cloudfront-Forwarded-Protoheader for correct HTTPS detection
Use when: Testing locally or in non-production environments.
Configuration:
enable_cloudfront = false
enable_route53_dns = falseURLs:
- Registry:
http://<alb-dns-name> - Keycloak:
http://<keycloak-alb-dns-name>
Features:
- HTTP only (no HTTPS)
- Direct ALB access
- Simplest configuration
Use when: You need both CloudFront and custom domain access paths.
Configuration:
enable_cloudfront = true
enable_route53_dns = true
base_domain = "mycorp.click"URLs:
- Registry (CloudFront):
https://d1234abcd.cloudfront.net - Registry (Custom):
https://registry.us-west-2.mycorp.click - Keycloak (CloudFront):
https://d5678efgh.cloudfront.net - Keycloak (Custom):
https://kc.us-west-2.mycorp.click
Note: This is NOT a security risk, but may cause user confusion. A warning is displayed during
terraform apply.
| Variable | Description | Required For |
|---|---|---|
enable_cloudfront |
Enable CloudFront distributions | CloudFront mode |
enable_route53_dns |
Enable Route53 DNS and ACM certificates | Custom Domain mode |
base_domain |
Base domain for regional URLs | Custom Domain mode |
keycloak_domain |
Full Keycloak domain (non-regional) | Custom Domain mode |
root_domain |
Root domain (non-regional) | Custom Domain mode |
The application detects HTTPS using the following header priority:
X-Forwarded-Proto: https(CloudFront and ALB deployments)- Request URL scheme (direct access)
CloudFront is configured to send X-Forwarded-Proto: https as a custom origin header. This is the same header that ALB uses, so the application code works consistently across deployment modes.
Note: We use
X-Forwarded-Proto(not a custom header likeX-Cloudfront-Forwarded-Proto) because Keycloak natively recognizes this header for HTTPS detection.
Symptom: Login succeeds but user is immediately logged out.
Cause: The Secure flag on cookies requires HTTPS detection to work correctly.
Solution: Verify the X-Forwarded-Proto header is being set by CloudFront. Check CloudFront distribution origin settings.
Symptom: After clicking login, Keycloak shows "Invalid parameter: redirect_uri" error.
Cause: The CloudFront URL is not in Keycloak's allowed redirect URIs for the mcp-gateway-web client.
Solution:
- Re-run
init-keycloak.shafter generating fresh terraform outputs:cd terraform/aws-ecs terraform output -json > scripts/terraform-outputs.json export INITIAL_ADMIN_PASSWORD="your-password" ./scripts/init-keycloak.sh
- Or manually add the CloudFront URL to Keycloak:
- Go to Keycloak Admin → mcp-gateway realm → Clients → mcp-gateway-web
- Add
https://<cloudfront-domain>/*andhttps://<cloudfront-domain>/oauth2/callback/keycloakto Valid Redirect URIs - Add
https://<cloudfront-domain>to Web Origins
Symptom: The redirect_uri in the OAuth2 request looks like https:/oauth2/callback/keycloak (missing hostname).
Cause: The MCP Gateway ECS task doesn't have the correct REGISTRY_URL environment variable set.
Solution: Ensure domain_name is passed to the MCP Gateway module in main.tf:
domain_name = var.enable_route53_dns ? "registry.${local.root_domain}" : (
var.enable_cloudfront ? aws_cloudfront_distribution.mcp_gateway[0].domain_name : ""
)Then run terraform apply to update the ECS task definition.
Symptom: Keycloak returns an error about HTTPS being required.
Cause: Keycloak doesn't recognize it's behind HTTPS when accessed via CloudFront.
Solution: Ensure CloudFront is sending X-Forwarded-Proto: https header (not a custom header name). In cloudfront.tf:
custom_header {
name = "X-Forwarded-Proto"
value = "https"
}Also ensure Keycloak is configured with KC_HOSTNAME_URL (full URL with https://) instead of just KC_HOSTNAME.
Symptom: Login succeeds but API calls return 403 "Access forbidden".
Cause: Either the user doesn't have required group memberships, or the MCP scopes haven't been initialized on EFS.
Solution:
- Check user groups in Keycloak Admin → mcp-gateway realm → Users → select user → Groups
- Ensure user is in
mcp-registry-adminormcp-registry-usergroup - Run the scopes init task:
./scripts/run-scopes-init-task.sh --skip-build
- Restart the registry and auth services:
aws ecs update-service --cluster mcp-gateway-ecs-cluster --service mcp-gateway-v2-registry --force-new-deployment --region us-west-2 aws ecs update-service --cluster mcp-gateway-ecs-cluster --service mcp-gateway-v2-auth --force-new-deployment --region us-west-2
Symptom: Accessing the registry URL shows the default nginx welcome page.
Cause: The nginx default site configuration is intercepting requests before they reach the registry.
Solution: The docker/registry-entrypoint.sh should remove the default site:
rm -f /etc/nginx/sites-enabled/defaultRebuild and redeploy the registry container.
Symptom: terraform apply hangs on ACM certificate validation.
Cause: Route53 hosted zone doesn't exist or DNS propagation is slow.
Solution:
- Verify the hosted zone exists:
aws route53 list-hosted-zones - Check the
base_domainmatches your hosted zone - Wait for DNS propagation (up to 5 minutes)
Symptom: CloudFront returns 502 Bad Gateway.
Cause: ALB is not responding or security group blocks CloudFront.
Solution:
- Verify ALB health checks are passing
- Ensure ALB security group allows inbound from CloudFront (via prefix list or
0.0.0.0/0) - Check ECS service is running and healthy
While out of scope for automation, you can manually configure a custom domain in front of CloudFront:
- Create an ACM certificate in
us-east-1(required for CloudFront) - Add the custom domain as an alternate domain name (CNAME) in CloudFront
- Create a Route53 ALIAS record pointing to the CloudFront distribution
- Update Keycloak
KC_HOSTNAMEto use the custom domain
Refer to AWS CloudFront documentation for detailed instructions.