Guide · AWS ACM · TLS Certificates

AWS Certificate Manager for MCP Servers — TLS Provisioning, Validation, and Renewal

AWS Certificate Manager (ACM) provisions free public TLS certificates for any domain you own, attaches them to Application Load Balancers, API Gateways, and CloudFront distributions, and auto-renews them 60 days before expiry — all at zero cost for certificates attached to AWS services. For MCP server operators, ACM removes the most common cause of unplanned downtime: a forgotten certificate renewal. The catch is that ACM certificates cannot be exported — they can only be used with ACM-integrated AWS services. If your MCP server runs on an EC2 instance or container that terminates TLS directly, you need either ACM Private CA (for internal certificates) or a third-party certificate from Let's Encrypt. See the ACM with ALB guide for the HTTPS termination pattern that works with ACM public certificates.

TL;DR

Request a public certificate with DNS validation, add the CNAME record to Route 53 (or your DNS provider), and attach to an ALB or CloudFront. ACM handles renewal automatically as long as the CNAME record stays in DNS. For ALB integration see ACM with ALB. For CloudFront (must use us-east-1 certificate) see ACM with CloudFront. For internal mTLS between MCP components see ACM Private CA.

Request a public certificate

ACM public certificates are issued by Amazon Trust Services, a publicly trusted CA. Certificates are free for use with ACM-integrated AWS services. There is no charge per certificate, no charge per renewal, and no charge for wildcard certificates.

# Request a certificate for your MCP server's domain
aws acm request-certificate \
  --domain-name api.mcp-server.example.com \
  --validation-method DNS \
  --subject-alternative-names "*.mcp-server.example.com" "mcp-server.example.com" \
  --key-algorithm EC_prime256v1 \
  --tags Key=Service,Value=mcp-server Key=Environment,Value=production \
  --region us-east-1
# Output: { "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc-123..." }

# Retrieve the DNS validation records (CNAME name+value) you must add to your DNS
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/abc-123 \
  --query 'Certificate.DomainValidationOptions[].ResourceRecord'
# Output: [{ "Name": "_abc123.mcp-server.example.com.", "Type": "CNAME", "Value": "_xyz789.acm-validations.aws." }]

Choose DNS validation over email validation: DNS validation is permanent (the CNAME record stays in DNS and ACM uses it for all future auto-renewals), while email validation requires a manual step on every renewal cycle. DNS validation is the only approach that supports fully automated certificate lifecycle management.

# If your domain is in Route 53 — add the validation CNAME automatically
# (requires the hosted zone ID for your domain)
HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
  --dns-name mcp-server.example.com \
  --query 'HostedZones[0].Id' --output text | sed 's|/hostedzone/||')

VALIDATION_RECORD=$(aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/abc-123 \
  --query 'Certificate.DomainValidationOptions[0].ResourceRecord')

RECORD_NAME=$(echo $VALIDATION_RECORD | jq -r '.Name')
RECORD_VALUE=$(echo $VALIDATION_RECORD | jq -r '.Value')

aws route53 change-resource-record-sets \
  --hosted-zone-id $HOSTED_ZONE_ID \
  --change-batch "{
    \"Changes\": [{
      \"Action\": \"UPSERT\",
      \"ResourceRecordSet\": {
        \"Name\": \"$RECORD_NAME\",
        \"Type\": \"CNAME\",
        \"TTL\": 300,
        \"ResourceRecords\": [{\"Value\": \"$RECORD_VALUE\"}]
      }
    }]
  }"

# Wait for validation to complete (typically 2-5 minutes with Route 53)
aws acm wait certificate-validated \
  --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/abc-123
echo "Certificate validated and issued"

Certificate validation methods compared

AspectDNS validationEmail validation
Auto-renewalFully automatic — ACM re-validates using the permanent CNAME recordRequires manual email click on every renewal (every 13 months)
SetupAdd one CNAME record per unique domain name (wildcards share a record with the base domain)Receive email at domain admin, postmaster, webmaster, hostmaster, or administrator @domain
Wildcard supportYes — *.example.com uses the same CNAME as example.comYes
Works if you don't control DNSNoYes — useful for domains controlled by a different team
Validation TTLCNAME must remain in DNS; deletion = failed renewal at next cycleEmail expires in 72 hours; request a new one if missed
Suitable for automationYes — full IaC with Terraform/CDKNo — human in the loop
Multi-region certificatesOne CNAME validates all regions; request the same domain in each region without re-validatingEmail re-sent per region request

Key algorithm choices

ACM supports RSA 2048, RSA 4096, and ECDSA P-256 and P-384. For MCP server deployments the choice affects TLS handshake performance and compatibility:

AlgorithmCLI flagHandshake speedCompatibilityRecommendation
RSA 2048RSA_2048ModerateMaximum — works with all TLS clients including legacyDefault; use when broad compatibility matters
RSA 4096RSA_4096Slow — 4× more CPU than RSA 2048HighNot recommended; security gain is marginal, cost in handshake latency is significant
EC P-256 (ECDSA)EC_prime256v1Fast — 10-20× faster than RSA 2048High — all modern clients (TLS 1.2+)Best choice for new deployments; smaller certificates = faster handshakes, lower compute cost on ALB
EC P-384 (ECDSA)EC_secp384r1Moderate — slower than P-256HighOnly if P-384 is a compliance requirement; P-256 provides equivalent security for most threat models

ECDSA P-256 certificates (EC_prime256v1) are the modern choice: smaller size (smaller certificates fit in fewer TLS handshake packets), faster signing, and lower per-connection compute cost on ALBs under high concurrency. MCP clients using modern HTTP stacks all support ECDSA. The only reason to use RSA 2048 is compatibility with legacy clients that don't support ECDSA — for MCP server deployments where all clients are modern AI agents or developer SDKs, EC_prime256v1 is the better default.

# You cannot change the key algorithm after a certificate is issued.
# To migrate from RSA to ECDSA: request a new certificate, attach to ALB/CloudFront,
# then delete the old one. No downtime — ALB/CloudFront negotiates the new cert immediately.

# Request ECDSA P-256 certificate (recommended for new MCP server deployments)
aws acm request-certificate \
  --domain-name mcp.example.com \
  --subject-alternative-names "*.mcp.example.com" \
  --validation-method DNS \
  --key-algorithm EC_prime256v1 \
  --region us-east-1

# Check certificate details including key algorithm
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/abc-123 \
  --query 'Certificate.{Status:Status,Algorithm:KeyAlgorithm,Expiry:NotAfter,SANs:SubjectAlternativeNames}'

Certificate lifecycle and auto-renewal

ACM certificates are valid for 13 months (395 days). ACM attempts renewal starting 60 days before expiry. For DNS-validated certificates, renewal is fully automatic — ACM queries the validation CNAME record that is already in DNS. For email-validated certificates, ACM sends a new validation email that must be clicked within 72 hours.

# List all certificates with their expiry dates (useful for a monthly audit)
aws acm list-certificates \
  --certificate-statuses ISSUED \
  --query 'CertificateSummaryList[].{Arn:CertificateArn,Domain:DomainName}' \
  --output json | \
jq -r '.[] | .Arn' | \
while read ARN; do
  aws acm describe-certificate \
    --certificate-arn "$ARN" \
    --query 'Certificate.{Domain:DomainName,Expiry:NotAfter,Status:Status,RenewalStatus:RenewalSummary.RenewalStatus}' \
    --output json
done

# Check renewal status for a specific certificate
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/abc-123 \
  --query 'Certificate.RenewalSummary'
# RenewalStatus values:
#   PENDING_AUTO_RENEWAL — ACM hasn't started the renewal attempt yet
#   PENDING_VALIDATION   — DNS/email validation in progress (DNS should resolve quickly)
#   SUCCESS              — renewed; new cert will be deployed at next attachment sync
#   FAILED               — validation failed; check DomainValidationOptions for reason

The most common cause of renewal failure is deleting the DNS validation CNAME record. This happens when DNS zones are migrated to a new provider, when TTL-zero records are cleaned up by automation, or when the record was never added to a subdomain's zone (common when the subdomain has a delegated zone that the base domain's CNAME doesn't cover). Never delete ACM validation CNAME records. They are harmless to leave permanently — ACM uses them only for validation queries.

# Monitor for certificates within 60 days of expiry using CloudWatch
# ACM emits a DaysToExpiry metric automatically — no setup needed
aws cloudwatch put-metric-alarm \
  --alarm-name ACMCertExpiry60Days \
  --alarm-description "ACM certificate expiring within 60 days — check renewal status" \
  --metric-name DaysToExpiry \
  --namespace AWS/CertificateManager \
  --dimensions Name=CertificateArn,Value=arn:aws:acm:us-east-1:123456789012:certificate/abc-123 \
  --statistic Minimum \
  --period 86400 \
  --evaluation-periods 1 \
  --threshold 60 \
  --comparison-operator LessThanOrEqualToThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:cert-expiry-alerts \
  --treat-missing-data breaching

# EventBridge rule for ACM certificate expiry notifications (account-level)
# ACM sends events 45, 30, 15, 7, 3, and 1 days before expiry
aws events put-rule \
  --name ACMCertExpiryNotification \
  --event-pattern '{
    "source": ["aws.acm"],
    "detail-type": ["ACM Certificate Approaching Expiration"]
  }' \
  --state ENABLED

aws events put-targets \
  --rule ACMCertExpiryNotification \
  --targets '[{
    "Id": "SendToSNS",
    "Arn": "arn:aws:sns:us-east-1:123456789012:cert-expiry-alerts"
  }]'

ACM limits and multi-region deployments

ACM certificates are regional — a certificate issued in us-east-1 cannot be attached to an ALB in us-west-2. For multi-region MCP server deployments, request the same certificate in each region. DNS validation only requires the CNAME to be added once — subsequent requests for the same domain in different regions validate automatically against the existing CNAME.

LimitDefaultAdjustable
Public certificates per account per region2,500Yes — request via Service Quotas
Domain names per certificate (including SANs)10Yes — up to 100
ACM certificate validity13 months (395 days)No — fixed by CA/Browser Forum baseline
Certificate import limit (third-party certs)1,000Yes
AWS services that accept ACM certificatesALB, NLB, API Gateway, CloudFront, AppSync, Elastic Beanstalk, CloudSearch, Lightsail (limited)
EC2 direct TLS terminationNot supported — ACM public certs cannot be exported; use ACM Private CA or Let's Encrypt for direct TLS
# Request the same certificate in multiple regions for multi-region ALB deployment
# Region us-east-1 (primary)
aws acm request-certificate \
  --domain-name api.mcp.example.com \
  --validation-method DNS \
  --key-algorithm EC_prime256v1 \
  --region us-east-1

# Region us-west-2 (secondary)
aws acm request-certificate \
  --domain-name api.mcp.example.com \
  --validation-method DNS \
  --key-algorithm EC_prime256v1 \
  --region us-west-2

# DNS validation CNAME is the same for both requests —
# add it once and both certificates will validate.
# The CNAME value is deterministic per domain, not per certificate ARN.

Certificate expiry and MCP server uptime

An expired TLS certificate causes MCP clients to reject connections with a hard TLS error — no retry, no fallback, instant failure. For MCP servers in production, a certificate expiry is functionally identical to a server outage: all clients stop working simultaneously at the second the certificate expires.

ACM auto-renewal eliminates this risk for certificates attached to ALBs and CloudFront, but it does not protect against: DNS CNAME records being deleted (renewal fails), certificates used on EC2 instances managed by Let's Encrypt that miss a renewal cycle, or imported third-party certificates that ACM cannot auto-renew. AliveMCP monitors TLS certificate validity as part of its health checks — if your MCP server's TLS cert is within 14 days of expiry, AliveMCP fires an alert before your clients experience failures, giving you time to remediate regardless of how the certificate was provisioned.

Failure modes reference

SymptomCauseFix
Certificate stays PENDING_VALIDATION for more than 30 minutesDNS CNAME not propagated; wrong CNAME value copied; validation CNAME added to wrong DNS zone (base domain zone vs subdomain delegated zone)Verify CNAME with dig _abc123.mcp.example.com CNAME; check both the base zone and any subdomain delegated zones
Certificate renewal fails with FAILED statusDNS validation CNAME was deleted; domain expired; DNS provider changed without migrating the validation CNAMERe-add the CNAME from describe-certificate DomainValidationOptions.ResourceRecord; re-request certificate if status is stuck
Certificate issued but ALB shows "no valid certificate" for the domainCertificate not yet attached to the HTTPS listener; ALB listener targets the wrong certificate ARN; certificate is in a different region than the ALBAttach via ALB listener HTTPS certificate action; verify regions match; see ACM with ALB guide
"certificate not trusted" errors from MCP clientsTesting with ACM-like self-signed certificates; imported certificate without full chain; using ACM Private CA issuer that is not trusted by clientACM public certificates chain to Amazon Root CA — trusted by all major OS/browser trust stores; for Private CA, distribute the CA certificate to clients
Cannot attach ACM certificate to EC2 nginx/Apache directlyACM public certificates are not exportable — this is by designUse ACM with an ALB in front of EC2 (recommended); or provision certificates via Let's Encrypt certbot directly on EC2; or use ACM Private CA which supports certificate export
CloudFront returns old/wrong certificate after attaching new ACM certCloudFront certificate propagation takes up to 15 minutes globallyWait 15 minutes; verify with curl -I https://your-domain.com from multiple geographic locations; check CloudFront distribution deployment status