I have a simple site mysite.com served behind CloudFront distribution and maintenance.mysite.com single static page hosted on S3 also served behind CloudFront distribution.
I want to be able to switch between them on route53 level when my main site is not available, but CloudFront doesn't allow to have same domain name attached to the different distributions. As per docs https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html
Duplicate and overlapping alternate domain names
You cannot add an alternate domain name to a CloudFront distribution if the same alternate domain name already exists in another CloudFront distribution, even if your AWS account owns the other distribution.
What is the proper and fastest way to switch between main and backup pages on a route53 level?
I don't want extra load balancers / lambdas to be involved and DNS way is the preferable solution.
I think this depends on how you want to create www.mysite.com vs mysite.com. If, as you have in your diagram, all incoming requests are actually to mysite.com, then you can just have a CNAME* entry that points mysite.com to www. when that's up and running, and to maintenance. when it's in maintenance mode. However, if you want www. and mysite.com (with no subdomain) to both go to the same place and have that same place switch around, then you need to come up with another name for your production server. Then you can have
- prod.mysite.com
/
[www.mysite.com | mysite.com] -< CNAME* in Route53
\
- maintenance.mysite.com
CNAME is the standard DNS way to do this; however, I believe AWS charges for CNAME redirects and not for aliases, So, wherever I say CNAME above, you can actually create an A record in Route53, and then click on the "alias" switch and select "Alias to another record in this hosted zone".
There is no straightforward solution, so I'm posting workarounds from AWS support here as an answer
Workaround 1:
You need to have 2 CloudFront distributions. One of these would be “Blue” and the other, “Green”. The Blue distribution would need to have www.domain.com as the alternate domain name. Now, create a DNS record that points www.domain.com to the CloudFront distribution “Blue” which will act as Production environment now.
Moving on, add the CNAME *.domain.com to the CloudFront distribution "Green" (the other distribution).
Now, in this setup, a request to www.domain.com would land on the Blue Distribution, as it has www.domain.com as the ADN (which is more granular than *.domain.com). Now, when you want to make the “Green” distribution as production distribution, just remove the Alternate Domain Name from the "blue" distribution. In that case, there would be only one distribution that would satisfy the request for www.domain.com, the Green one (which has *.domain.com as ADN), and the request would be routed to that even if your DNS points www.domain.com to the Blue distribution (as CloudFront routes a request based on the Host header and will choose a distribution that has that domain as the ADN).
Workaround 2:
You need to have 2 CloudFront distributions. One of these would be “Blue” and the other, “Green”. Create a DNS record that points www.domain.com to the CloudFront distribution “Blue” which will act as Production environment now. Also, add www.domain.com as a CNAME(Alternate Domain Name) to the distribution “Blue”. Meanwhile you can test the other CloudFront distribution “Green”.
When you want to make the “Green” distribution as production distribution, you should first point the DNS record for www.domain.com to the CloudFront distribution “Green”. Even though the DNS points to the “Green” distribution, the request will still be routed to the “Blue" CloudFront distribution because “Blue” CloudFront distribution has the CNAME(Alternate Domain Name) for www.domain.com (CloudFront will try to route the request to a CloudFront distribution that has the same CNAME(Alternate Domain Name) value as the value of the host header). Wait for a few hours for the new DNS record to propagate. Then, remove the CNAME from CloudFront distribution “Blue” and add it immediately to the CloudFront distribution ”Green”. Now all the requests will be routed by CloudFront to the “Green” CloudFront distribution since the “Green” CloudFront distribution has the CNAME(Alternate Domain Name) www.domain.com.
This workaround would involve some downtime when you move the CNAME from the "blue" distribution to the "green" distribution, so I would recommend going with the first workaround only. Also, please test this on a test environment first before testing it on the production distributions.
Related
I am currently implementing Canary Release and Blue Green Deployment on my Static Website on AWS S3. Basically, I created two S3 bucket (v1 and v2) and 2 cloud front (I didn't append the CNAME). Then, I create 2 A alias records in Route 53 with 50% each weight routing policy. However, I was being routed to v1 only using both laptop and mobile to access my domain. I even ask my colleague to open my domain and they're being routed to v1 as well.
It really puzzled me why there's no user being routed to v2?
AWS Static Web in S3
The assigned dyyyexample.cloudfront.net and dzzzexample.cloudfront.net hostnames that route traffic to your CloudFront distributions go to the same place. CloudFront can't see your DNS alias entries, so it is unaware of which alias was followed.
Instead, it looks at the TLS SNI and the HTTP Host header the browser sends. It uses this information to match with the Alternate Domain Name for your distribution -- with no change to the DNS.
Your site's hostname, example.com, is only configured as the Alternate Domain Name on one of your distributions, because CloudFront does not allow you to provision the same value on more than one distribution.
If you swap that Alternate Domain Name entry to the other distribution, all traffic will move go the other distribution.
In short, CloudFront does not directly and natively support Blue/Green or Canary.
The workaround is to use a Lambda#Edge trigger and a cookie to latch each viewer to one origin or another. Lambda#Edge origin request trigger allows the origin to be changed while the request is in flight.
There is an A/B testing example in the docs, but that example swaps out the path. See the Dynamic Origin Selection examples for how to swap out the origin. Combining the logic of these two allows A/B testing across two buckets (or any two alternate back-ends).
What you are explaining should work if you make use of "overlapping aliases" in Cloudfront. You configure one distribution to listen to app.example.com and the other one to *.example.com and use Route53 weighted routing for app.example.com
However weighted routing might not be ideal solution for canary releases. This is due to DNS propagation/caching and the fact that it is not sticky.
Like Michael suggests you might want to look into having 1 cloudfront and routing to bucket A/B using Lambda#Edge or Cloudfront functions.
Here is an example.
As per this Amazon's article I was trying to make the whole WordPress website work behind AWS CloudFront. Not just the static files but the whole website (it can be done with setting up proper cache behaviors). However if you use the bare domain (example.com, without www) it seems that's impossible.
Namely, if the origin of a CloudFront distribution is example.com, and if you put a CNAME for example.com in that same distribution CloudFront will sporadically produce 403 Error. After some digging I found out that this is expected behavior since with this setup, where origin and the CNAME values are the same, CloudFront will look for the origin onto itself and produce error.
So how can one use naked domain and use CloudFront as a proxy at the same time?
Update:
I've implemented the origin.example.com solution suggested in the comments. I was getting an error but now it works.
The origin in the CF distribution is origin.example.com.
CNAME in the CF distribution is example.com.
In the Cache Behavior settings in the CF distribution the Host header is whitelisted.
In DNS origin.example.com points to the server's IP with an A record.
In DNS example.com points to the CF distribution with an ALIAS-A record.
The only beef I have with this workaround is that this way the origin server's IP address is discoverable on the net. A script kiddie can accidentally access origin.example.com and the server's true IP address is in the open, thus you're prone to DDoS. One of the many benefits of a proxy is that with it you're hiding the true server's IP address.
I'm currently using Cloudflare as a proxy mainly because of that reason. In the past I was hit with massive DDoS attack and my server's IP address was null-routed by the host, so I had to quickly hide behind Cloudflare and change the server's static IP. No headaches since then. I wanted to switch to CloduFront but using the bare domain seems not viable.
You have to create another hostname in DNS, pointed to the instance, such as origin.example.com. But the instance does not need to know about this name.
Create a CloudFront origin using this new hostname as the origin domain name, and then in the Cache Behavior, whitelist the Host header for forwarding to the origin.
In DNS, point example.com only to CloudFront.
CloudFront will then use the alternate name to find the instance's actual IP address, but will preserve the original hostname (example.com) in the request that is sent to the origin.
If anyone else runs into this issue, the problem may be with the certificate. If your certificate is for "*.example.com" make sure it also has "example.com" added. If not, create a new one.
When using CloudFront to cache an entire web site, use an A-ALIAS record for both the naked domain (example.com) and for www (www.example.com) that resolves to the CloudFront Domain Name. If you are using SSL on CloudFront, ensure that both domain names are in the certificate.
I'm replacing a legacy website with a new one, in stages. From a user perspective, all existing URLs must remain the same, but certain paths should serve new pages.
I have two origin servers: the legacy one (www.mysite.com) and the new, EC2 one (www.ec2-loadbalancer.com) – obviously mock URLs for privacy reasons.
I've created an AWS CloudFront distribution with a CNAME setting of www.mysite.com. Within this distribution I've created two origins domains:
www.mysite.com
www.ec2-loadbalancer.com
Within CloudFront I've configured some behaviours so that paths like /foo are sent to my EC2 load balancer origin, and all other paths (eg. default) are sent to www.mysite.com.
From a DNS perspective, I've added a CNAME record of www.mysite.com which points to my Cloudfront host domain (eg. foo.cloudfront.net.). The A record for this domain points to the IP of the legacy server.
I launched all of this today and it seems to have worked, but I'm seeing intermittent 403 errors on the site, and two hours after making the change (there was no "www" CNAME before, so TTL shouldn't make a difference), some browsers are still serving the site from the original IP (rather than the CloudFront one).
Have I configured this properly? I couldn't work out how to do this via the A record – that points to the IP of the legacy server, and CloudFront doesn't allow me to enter an IP address as an origin. Should I have pointed the www CNAME at the IP address, made the A record point at CloudFront instead? I'm a bit lost here.
On the other hand, it could all be a propagation thing, but I'm wary having seen 40x errors hours after making the change.
i think you should create an A record (for the named domain name) with an alias pointing to the cloudfront distribution. It should solve the problem.
i.e. Use Alias name instead of IP address and point your domain to cloudfront:
It's a shame you can't share the domains with us to help debugging, but at the very least, dig is your friend. For instance:
$ dig membership.theguardian.com
...
;; ANSWER SECTION:
membership.theguardian.com. 367 IN CNAME i.global-ssl.fastly.net.
i.global-ssl.fastly.net. 12 IN A 151.101.128.67
i.global-ssl.fastly.net. 12 IN A 151.101.64.67
i.global-ssl.fastly.net. 12 IN A 151.101.0.67
i.global-ssl.fastly.net. 12 IN A 151.101.192.67
...tells you that membership.theguardian.com is pointing to Fastly by CNAME. You can check with alternate DNS servers, like Google's DNS on 8.8.8.8, by doing this:
$ dig #8.8.8.8 membership.theguardian.com
...so you can see how other people are resolving your domains.
From a DNS perspective, I've added a CNAME record of www.mysite.com
which points to my Cloudfront host domain (eg. foo.cloudfront.net.).
The A record for this domain points to the IP of the legacy server.
I'm not a DNS expert, so it's possible I'm not understanding you here, but this sound like it introduces ambiguity? To me this sounds like you have two different records for the same www.mysite.com domain, one of which points to CloudFront, and the other to the IP of your legacy server. Depending on how that gets resolved a browser could be sent to one or the other?!
www.mysite.com should point only to CloudFront. I would personally just use a CNAME for this.
You should have unambiguous addresses for both your legacy server and your EC2 Elastic Load Balancer - I would personally give them their own clear domain names, to avoid confusion (eg. legacy.mysite.com & beta.mysite.com) - and in CloudFront refer to only to those clear names when you're directing traffic (eg. passing traffic on to www.mysite.com as a way of going to the legacy server would be confusing).
Good luck!
I am currently using Amazon Route 53 for my DNS setup and a custom origin (web server outside of Amazon). I'd like to add CloudFront to the mix but I'm not too sure how to set it up?
I've seen Amazon's guide on setting up S3 with Route 53 and CloudFront, but I can't seem to locate any information on doing all this with a custom origin.
Should I be setting it up to work as follows?
CloudFront pulls the data from the naked domain's IP address
The 'www' is just an alias of the CloudFront distribution
I originally planned to host my content on S3 but decided against it because I'd like more control over the hosting (for example, having the ability to use an .htaccess file and ban hacker IPs, etc).
Thanks.
OK so this is how I managed to solve it in the end:
Origin Server:
In cPanel (on my origin server) I created a sub-domain called origin.domain.com
origin.domain.com shares the same document root as domain.com
My .htaccess file redirects domain.com to www.domain.com:
Amazon CloudFront:
The "Alternate Domain Names (CNAMEs)" is set to www.domain.com
The origin is set to origin.domain.com
Amazon Route 53
The A record for domain.com is set to my origin server's IP address
The A record for www.domain.com is set to an alias for the CloudFront distribution
origin.domain.com is a CNAME for domain.com
Thanks to Matt Houser and Bruce P for their help, by the way. :)
Assuming your have your origin at origin.domain.com, create your CloudFront distribution, using http://origin.domain.com as the origin.
Create your www.domain.com DNS entry in Route 53, making it an "Alias" for the CloudFront distribution.
One possible alternative to .htaccess is to use WAF on your CloudFront distribution. This way, you can permit/deny based on IP address.
I’m trying to add a route 53 record set that points to my cloudfront distribution. However, when I select ‘create record set’ in route 53 and click the alias target in the subsequent panel, the cloud front distribution is not listed. All I get is ‘No targets available’. My Distribution has been created and is enabled (and is working). I have added a CName to my distribution with the same domain name that I’m setting up in Route53, but it still doesn’t show.
How do I get my distribution to show in the Alias Target field so that I can point a Route53 ‘a’ record to it?
Thanks
Combining several correct but incomplete answers:
Only A records and AAAA are supported. Not CNAME records.
The Route53 "Alias Target" box matches against CloudFront distributions' "Alternate Domain Names" field. If you're creating a new record set for something.example.com, you should have already set the alternate domain name for one of your distributions to something.example.com.
The Route53 Management Console can be slow, and it might not find your distribution right away — wait until the distribution status is Deployed.
Make sure you have set one or more Alternate Domain Names for you distribution, otherwise it won't be listed on the target combo for Route53 Alias.
As far as I understand, that's the same as configuring ServerAlias on your Apache's VirtualHost (or the correspondent for Nginx and so on). Without it, your requests wouldn't be identified as destined to that distribution when it gets there.
From AWS's documentation:
If you're using CloudFront to distribute your content, you can use Amazon Route 53 to route queries to your CloudFront distribution. The name of your Amazon Route 53 hosted zone (such as example.com) must match an alternate domain name in the CloudFront distribution. You cannot route queries to the CloudFront domain name for your distribution (such as d111111abcdef8.cloudfront.net). The following procedure assumes that you have already registered the applicable domain names.
Make sure it's an A record rather than a CNAME record (weird, I know). I found that buried in the documentation here:
http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-alias.html
If your distribution does not show as an alias target, you can always manually copy and paste the d123.cloudfront.net (replace d123.cloudfront.net with the actual DNS name of your distribution) in to the target. This will allow you to create the alias record.
Make sure your CloudFront distribution includes the name of your site (example.com )!
I was having the same issue and spent well over an hour trying to solve the problem...
TL/DR
Set your Origin ID in the origin in your Cloudfront Distribution to be the same as the domain name you are trying to create an alias for
More Detail
I struggled with this for some time.
In the end I compared a working CloudFront distribution which did show up in Route 53 with one that did not.
What I noticed was that the Origin Id specified in the origin for the distribution was not the domain name for my site.
This option is found in: CloudFront Distributions > [Id of distribution] > Origins and Origin Groups > Origins.
I only had one origin listed where the path was the name of a public s3 bucket. This entry also had an Origin ID field. When I updated this to be my domain name (without the www prefix) e.g. testdomain.com then I was able to see this cloud front distribution in the route 53 alias drop down.
You have to fill the Alternate Domain Names (CNAMEs) field e.g. use
www.my_site.com
*.my_site.com
For SSL Certificate field select
Custom SSL Certificate (example.com)
for this you will have to create and verify your domain with ACM, ACM has to be created in Virginia.
After that you will be able to see the Cloudfront in R53.
The trick was to enter the www before the domain because CloudFront matches against that alternate domain name with www or whatever subdomain you use. Type www or your subdomain and it will find the distribution.
It was taking forever for my cloudfront distribution status property to read deployed.
However inputting the cloudfront domain url into my address bar brought me to my website, aka the cloudfront domain url was live.
Feeling impatient, I copied this domain address and pasted it into the alias target field.
It worked!