 So, alright everyone, thanks for coming out to learn how to deploy and manage Ruby on Rails applications on Amazon Web Services. So a quick introduction to who we are. So all three of us work on the AWS SDKs and tools team. I'm Alex Wood, you can find me on Twitter and GitHub. And in the back handing out codes, we have Trevor Rowe and Lauren Segal who you can also find on Twitter and GitHub. And if you have any questions during the lab, feel free to raise your hand and Trevor and Lauren will come down and help you out. And during the parts where we're just working on exercises, you can ask questions of me up here as well. So what are we doing today? We have a Ruby on Rails sample application that's linked inside the instruction document. You don't need to bring it down or clone it or anything. But it's there so you can look around, see how we did the integrations, play around with it further after the lab is done. We are going to deploy that to Amazon Web Services using AWS OpsWorks. After that, we're going to use Amazon Simple Email Service to send action mailer messages using the new AWS SDK Rails gem. And we may run over time for the last part, but all the instructions are there. We're going to show you how to cache the Rails asset pipeline using Amazon CloudFront. So here's a slide that was up while everyone was coming in. So just a quick show of hands again, if you do not have an AWS account yet, could you raise your hand? Cool, so for this lab, you will need an AWS account. And with the credit handouts that we're giving out, you can create an account straight from there. Could you raise your hand if you don't have AWS credits yet? So Trevor Lauren will be buying a second with a credit for you. So we'll take a couple of minutes here just to make sure everything is set up, so log in to your AWS account or make it if you don't have one yet. Apply your credits, which you shouldn't need for the lab, but it's 50 bucks, I'd encourage everyone to take it and experiment afterwards, try things out. And there's also a tiny URL link to the instructions page for the lab. So if anyone can't get to that page, let me know as well. And we'll take about one more minute for this. And while we have these pauses, feel free to shoot a question to me if you have one at any time. Yeah, so just a double check, is there anyone who does not have their AWS credits in their hand and applied yet? Raise your hand so Trevor Lauren can find you. Yeah, I mean, if you have an account, you can still apply the credits to it. The lab is, we're using the smallest instance types and we're cleaning everything up afterwards. So, and if you're in the AWS free tier, that should cover some of the cost as well. But definitely take a credit anyway and keep playing around. We'll talk a little bit about what you can do at the end of the lab as well. And we'll be hanging around afterwards if anyone wants to ask more questions or try more stuff out. All right, so let's talk about what we're building. So we're building a two layer web application with AWS Opsworks. So we're going to start by creating an Opsworks stack, which you can think of as a container for all of the other resources that our application deployment is going to have. We're going to have two layers, as mentioned before. A Rails app server layer which will contain any instances that are running Ruby on Rails. And separate from that in the connection configured by Opsworks, a MySQL layer that is going to be running a single EC2 instance with MySQL on it. We're also going to be from the app layer, sending out emails to user accounts with Amazon SES and the AWS SDK Rails gem. And we're going to cache the Rails asset pipeline using Amazon Cloud front. So why Opsworks? This is a question I've heard a few times while we've been talking about the lab earlier in the conference. I wanted to kind of strike a midpoint on the convenience and control scale. So Opsworks gives you a lot of fine-grain control over how your instances are configured, how you scale them, and where they live. Which we have other options such as now AWS code deploy, CloudFormation, or manually using instances that give you more fine-grain control or choices like Amazon EC2 container service and Elastic Beanstalk, which give you more convenience. So we're definitely happy to talk about any of the other options afterwards, but this is a nice middle ground, I think, for the lab that we're doing today. So I think we already talked a lot about these, but just a review of some of the key concepts we're going to talk about. So AWS Opsworks uses Chef to help manage and configure your AWS instances. So we talked about the concepts of a stack and layer. There's also a concept of an app, which contains all the configuration needed to deploy your application to your instances. We're also using the new AWS SDK Rails Ruby gem. So out of curiosity, we released this a few weeks ago. Can you raise your hand if you've tried that gem out before? Awesome, so a few of you have seen that. And that builds on top of the AWS SDK for Ruby V2 that we released last year. We're also going to be covering a little bit about AWS identity and access management, talking about how we can manage our credentials safely. And best follow the principle of least privilege. Including IAM roles for Amazon EC2, which the AWS SDK Rails gem can use. And we're also going to review Amazon SCS and CloudFront. So we have a Rails application. What do we do so that we can actually deploy it to AWS Opsworks? Right here is the diff. Can everyone see it? It might be. Yeah, so I'll just review what it is. It's a change to the gem file where we say in production, we use the unicorn gem in the MySQL 2 database adapter gem. And we create a file called before sim link in a deploy folder in our Rails application, which essentially pre-compiles our static assets during the deployment phase. So before sim link is a chef hook. Who here is familiar with chef hooks? Cool. So this is already provided for you in the repo we're deploying. So we don't have to make these changes. This is just a review of the changes you would have to make to take a Rails application you have and get it so it will deploy and run on AWS via Opsworks. So now we're gonna get into the first exercise. We're going to take our sample application and deploy it to AWS with Opsworks. So to start, we're gonna create a stack. We're going to create the application in database layers. And then we're going to create and deploy an application. So the first exercise and the instruction sheet does have a link so you can jump around the different exercises. Is to create an Opsworks stack. So I'll leave you guys a few minutes to do that. And if you have any questions, feel free to let me know at any time. Yeah, so it's just tinyurl.com slash Rails comp 2015-AWS. And if you're watching this on video, I'm going to keep that link up after the conference. And if the link is not up for any reason, feel free to get a hold of us so I can remediate that. Does everyone have that now? So raise your hand if you don't have the instruction sheet open. Give you guys a minute. Are we good to go on the instruction page? Raise your hand if you don't have it. One thing I want to call out while you're making your stacks as well, is to check your VPC option. So if you do not have a default VPC, so if I look at these VPCs, I have a default VPC and one that I created earlier. I would choose the default VPC cuz that'll work right out of the box. And if you do not have a default VPC option available, please raise your hand so Trevor and Lauren could help you out. If you don't have a default VPC, what region are you in? So the question was what is a VPC? And so VPC stands for virtual private cloud. So your instances inside a VPC, you can have control over what kind of inbound and outbound traffic is allowed, for example, and set up different subnets. So it's sort of a way to handle networking for your instances. So for example, as you were to expand on this app, you might say that your app and database instances should not be accessible from the public internet that they can only be accessed through a load balancer instance or SSH traffic through a bastion server. And if you have a VPC, it makes it easy to set that up. So for the purposes of this lab, we're just deploying in it and they're gonna be fairly permissive. The instances will be publicly accessible. But we'll have a little bit of a discussion at the end is how you could further productionize the application as you iterate on it. So in additionally, while you're creating this stack, you'll notice the instruction sheet. It has a instruction first to make an SSH key. Strictly speaking, you don't have to do this, but it's definitely recommended in case something goes wrong. We'll be able to SSH under the instances and see the logs. And if you have an existing SSH key, you can import it or just use that when you're creating the stack. So frequently asked question has been what should I name my key pair? You can name it anything you'd like. I named mine RailsConf. The trick is you wanna make sure that you know the key you're using is on your machine and then when you add that to the stack, it means you'll be able to SSH to your instances. So for the purposes of the lab, we're using a database layer that OpsWorks provides for you. In the Appendix section of the instructions, I've shown how you can use Amazon RDS for either Postgres, Microsoft SQL Server, Oracle, or even MySQL instances with RDS and failover. So there are further instructions about how you could do that and you could follow along with that after the lab. And then in other cases, so what OpsWorks will do is it will wire up your connection to your database. So if you wanted to use a different type of database instance, you could configure that in your Rails application and Rails would just connect to that. This is a show of hands, who has their stack created? So we'll leave a few more minutes for that. No, you don't have to create the whole thing. Just having created the stack and then the next exercise is going to be to create the layers. Yeah, so sorry, just to make, yeah. Raise your hand if you have not made the, if you have not gone through the add stack form yet. If you haven't made the layers yet, that's okay. That's the next exercise. And then raise your hand if you need help getting that set up. So while they're working, do you have a question I can help with? So the question was if creating a key is necessary. Again, you don't need to create an SSH key, but if something goes wrong later with your application and you don't have an SSH key, we don't have a way to look at your logs. So I would highly recommend it. And then if you have created your stack and you'd like to move on to the next exercises, feel free. I think this first exercise probably takes the longest with all the initial setup we have going on. So for the add stack form, most of the fields are going to use the defaults. But if you look in the exercise instruction, I list out a few that you'll want to change. One that is important is you want to create new IAM instances, or new IAM roles, because we're going to edit them. And if you don't create a new role, your change could be. If you had multiple stacks, you would be changing the permissions on all of them at once. So it's a best practice to create a new role anytime you're creating a new stack. So the question was, if we need to create an elastic load balancer. So we're not creating an elastic load balancer during this lab. I'm gonna go back to the, so in this lab, simply for time purposes, we're going to directly connect to your application server. It is a best practice to have a load balancer. But for the sake of time, we're simplifying the architecture. And we'll talk a bit at the end about how you would design things as you iterate on this design. So the next step is Exercise 1B on the instruction sheet, which is we're going to create the opsworks layers and launch an instance in each of them. And again, where we're using non-default options, that should be in your instruction sheet. And I also added for many of these a screenshot that you can compare against. Sure, so the question was, what would be the difference of choosing an instance store versus an EBS back store? For the sake of this lab, there is no difference. The difference you would find if, for example, you're running your database on instance storage, if that instance goes down, you lose your database and everything on it, unless you have snapshots and backups that you're creating. If it's an EBS backed instance, if the instance were to go down, you would still have the EBS instance with your hard drive on it, that you could attach to a new instance that you create to replace your failed instance. Does that answer your question? So the question is, when would you choose instance store? And the recommended default in opsworks is to choose an EBS backed instance. But for example, if you feel that the storage on your instance is enough, say for your application server, and you don't care about anything on it because it's stateless, you could choose an instance store. And if the server goes down, it doesn't matter. And another thing to remember is we're creating MySQL opsworks layers, we're not creating RDS layers. This is simply a matter of the fact that using an RDS instance takes a little bit more time. And for the sake of the lab, we're going with the quicker time option. But we do have instructions in the instruction sheet or a link to a blog post that will show you how you could switch this over to use RDS. Now I'd also recommend that you keep an eye on the instance size that you can select. As you can see here, the default is a C3 large, which is going to be a little bit more expensive than a T2 or T1 micro. But the smallest instance types are more than enough to run our sample application. And then once you get to this point where you have both layers created and your instances are spinning up, then you're done with this exercise. The instances will take a few minutes to set up and you can work on the next steps while they do. So the question was about the fact that the instructions say to create the instances in a VPC. So this is based on your stack settings. Whatever VPC you assign to your stack is the VPC the instances will be launched in or if you are in USC S1 without a VPC, they'll just be launched into EC2 classics. So if you take a look at the instance creation screen, you'll notice you can choose the subnet that it goes into. The default subnet is going to be fine for all of these and this is just where in the VPC the instances go. Does that answer your question? Yeah, so the question was that I mentioned this was running on Chef. And so what is going on during the running setup phase? So I'm going to go to a different screen on here for a moment. That I think will help demonstrate that. So when you look at your layer configuration, remember that layers are telling you how everything is configured. So if you look at the recipes page for a given layer, it shows you during setup configured deployments and so on. What Chef recipes are running and if you click through, it'll actually take you to the OpsWorks GitHub repo. And you can see the source of all the Chef that you're running. And you could also add your own recipes during these processes. So you can add or remove anything that you want to customize how your layer works. Maybe take a look here that the MySQL layer is going to have different recipes running than the Rails App Server layer was. So one thing the layers do is define what type of recipes are going to be run on any instances that are made in that layer. So that is configured at the, it was either the stack or the layer level. And you do have a drop down selection of what type of instance or what type of Linux distribution you're running on. The sake of lab using the most recent Amazon Linux will work fine. Cool, all right, so we're going to move on to the next exercise here. And there will be a bit of a pause at the end while we wait for some of the instances to catch up and create. So next we're moving on to exercise 1c, which is creating and deploying the OpsWorks application. So one quick note when you get to the app creation about the secret key base environment variable. Normally you're going to want to run rake secret on your Rails repo. But for the sake of what will actually work for deployment, any string of letters and numbers that isn't made entirely of numbers will work. So you can write your favorite sentence without spaces. That wouldn't be a production safe thing to do before the lab if you can't run rake secret and copy that value, this will do. But you would also want to make this a protected value, since once your secret key is set, you don't want people to be able to see what it is. The other thing to note is we're explicitly not enabling SSL. So this is purely a time saving thing. And also since I don't expect everyone to bring their own certificates. Obviously in a production setting you absolutely do want to have SSL set up for your instances, since otherwise you're sending things like user registration info and passwords, plain text over the wire. But for the sake of a sample application, it will work just fine without SSL enabled. And then once you have your application created, you're waiting for this to be the result of the instances screen, where both instances are online and running. And once you have that, you would go on to deploy. So while everyone's working on that, the two most common mistakes we had when we were testing out these instructions were not setting your secret key base, which if you don't set that, you'll get a white screen when you try to load your application. Just be completely blank because Rails will fail to start running. And failing to migrate your database. Since this is an initial deployment, we do have database changes we need to run. So when you go to the deploy screen, you'll turn migrate database to yes. And then opsworks will run rake db migrate against your database instance. And if you don't do that, you'll get the generic Rails error screen when you try to load your app. All right, so once you have your deployment successfully completed, to find your page, you would click through your app server's host name. And you can click through either the public DNS or the public IP to get to the app. And this is what you should see. And once you get to this point, you're done with exercise one. And if you have a few minutes, maybe play around, register an account, make a few tasks. When you make an account, it will be helpful for future tasks. If you use an email, you actually own. This doesn't do email verification, but you won't be able to send email to an account that you don't possess with a test account in NSES. It's also worth noting that at this step, if you try to subscribe to a task update and send mail, it's not going to work yet because we haven't configured it. Yeah, and for the sake of, I'm actually not sure how SES test accounts handle aliases. If you have to explicitly verify each one, I would actually be interested to see how that works out if you try that. Yeah, for the sake of a demo, registering one account on an email address you own will work to demonstrate everything we need to do, however. So you don't have to get too complicated with your emails if you don't want to. So just for a quick check, could you raise your hand if you've gotten to the running application page? Could you raise your hand if you haven't gotten that far, but you've got your deployment started? Do you raise your hand if you're still waiting for your instances to boot? Okay, that's good, that's not very many people. So what we'll probably do in those cases is just get your deployment started as soon as your instances boot, and we're gonna take a few minutes explaining what we're gonna do on the SES exercise. And that can happen while you're waiting for your instances to get gone. So we'll leave another minute for that. So the question was if there's a PostgreSQL layer. So AWS Opsworks only provides a MySQL database layer, as far as their EC2 managed instances. If you use an Amazon RDS layer, you can use any of the database offerings that RDS has. So you can use MySQL, PostgreSQL, Microsoft SQL Server, Oracle, or someday in the future, the Aurora database for RDS that Amazon is building. So the question was if you can create your own custom layers. I'm actually not sure on that front. I think that maybe more designed for you can customize the configuration of layers within your stack. But that's actually a good question. I'm going to get the definitive answer on that. And I will post that up after the talk. So the question was if you have a MySQL instance running on EC2, how do you get it so that the app can use it? So the way that Opsworks sets things up for you so that the database just works when you deploy is it uses the configuration values of the instance in the database layer and the database layer itself to create your database.yml file. So if you don't have your MySQL instance inside the MySQL layer, then it's not going to work. But I believe I can check this for you. You might be able to actually take that instance and register it. But maybe not for that. So bring your own database.yml file. For the sake of the lab, I wouldn't recommend it. Because I think you would have to change some of the underlying Chef recipes that are going to try to write it. Given enough time, you could do that. But for the sake of this lab, I would make sure you create an Opsworks owned MySQL instance. All right, so we're gonna take in our show of hands. Who has not started deploying the app yet? Okay, so we're gonna start on the explanation of the next exercise. And there should be time to catch up there. So the next exercise is sending emails using Amazon SES and the new AWS SDK Rails gem. So the sub exercises here are doing the configuration necessary to run the AWS SDK Rails gem, verifying an email so that you can send to and from mail for that with SES. And then we're gonna talk about how we configure an Opsworks IAM instance role profile. So the SDK has permissions to use Amazon SES to deliver your mail. So how do we change our application to be able to use the AWS SDK Rails gem? Again, apologies for the size of the screenshot here, but it's a one line change, so I can just explain it to you. If you require the AWS-SDK-Rails gem, prefer that you have the dependency locked to version 1.0. That's all you have to do. All of the, that's all you have to do in code. The configuration, creating the delivery handler, that will all be done for you by the SDK. As you're gonna see when you get into the exercise, all you need to provide is an environment variable for the AWS region you want the SDK to run in. So if you move to exercise 2A in your instruction sheet, we're gonna pick up from there. So, no, you don't have to. So this is actually a good question, let me repeat that. The question was, if you're using the AWS-SDK gem in your gem file, do you have to remove it? So there's two possible cases here. One is you're using the AWS-SDK gem version 2, in which case that is also what the AWS-SDK-Rails gem uses. And there's nothing you have to do, they'll just work. If you're using AWS-SDK version 1, it will still work. The V2 and V1 SDKs can coexist in the same project. And the reason this works is the AWS-SDK-Rails gem does its dependency on the highest level sub-gem of AWS-SDK, the AWS-SDK resources gem. So even if you depend on AWS-SDK version 1, you can use both in the same project. Does that answer your question? Excuse me. So one question I would ask is that, can you raise your hand if you did not create your stack in the Oregon region? Cool, so pay attention when you're creating the AWS-region environment variable. It should work in any region, although it'll be sending emails from a different region than your app is running in. But it's a good practice to have the AWS region be the region your stack is running in. So, yeah. So if you created it in Northern Virginia, which is probably the second most popular option, then the region you're looking for is US-E-1. If you created it in something other than that, then let us know. And then you don't need to do a deployment for this step because we're not using the SDK yet. So once you've changed your application, you're done with this exercise. So a quick note, if you're arriving here from another talk, welcome, make sure you raise your hand so Trevor and Lauren can find you and give you credits. I have known people who can catch up pretty quickly on what we're doing, but if you're just behind on the explanations, go ahead and work through the instruction sheet, which is one of your seat table mates should be able to give you. And then this will obviously be up on video so you can catch up on what we've been talking about up until now. So could you guys raise your hand if you have not added the AWS region variable to your application yet? So that is a availability zone. So the question was, does it matter if it's US West 2A or 2B? Those are availability zones. What you want to set is the region. So you do not want the A or B on the end. That won't work. So for Oregon again, that would be US-West-2. So the next exercise 2B is to set up your email for testing with Amazon SCS. So unless you have an existing production account, you essentially have to validate every email address that you send from or send to. We're going to set an environment variable for what address you're sending your email from, which should be one that you validate and own. And for the email you send to, that's going to be any account that you register inside your sample application. So that's the next exercise, and we'll have a few minutes for that. So the question was, what you have to do for this? So you go first to the Amazon SCS console under the verified email addresses link. There's a direct link to that inside the instruction seat, although fair warning, verified addresses are per region. So you want to make sure you're using the same region you set as your AWS region variable. And once you request to verify an email address, you have to go to that email account and click through the link. Once you've done that, it should show as verified in the console. Nope, that's it. Yeah, so then the next step you're going to do is the email handler inside our source code expects you to set the environment variable from email so that the action-mailer handler knows what email you're sending mail from. So you just configure that to be a verified email address that you own. Right, so I'm going to show how we do that here. So if you go to your application and you click edit, you would add a environment variable from email and have that be an email you verified and now, I'm sorry, you don't need to stop the app. But before it will take effect, you will have to redeploy it. So you can't deploy the app because it's running? That is strange because that's working for me. So I want to take a second to come look at that. For a application? Are you trying to edit the instance or the application? So just to follow along, if we go to the app screen and you're editing the application that requires you to stop it. So my best guess before I come down and take a look at it is you probably tried to stop your instance, which you don't have to do. So just to recap, I think my instructions were, sorry about that, unclear on this part. When you are editing your application, you are not editing your application server instance. You're editing the opsworks application itself. So if it's telling you that you need to stop an instance, you're on the instances editing screen. Follow the navigation bar to the apps editing screen. And then the exercise is done as soon as you click this link and have started a deployment. So I see a couple questions. So sandbox access means you have to verify every single email address that you send from or to. It just means you do not have production access. So if you have production access to Amazon SES or certain responsibilities about things like how often you get reported for spam, how often your emails bounce, and you have to apply for that, with a test account you just verify that you own every email you send from or to. So just go to the drop down and move to the Northern Virginia region. So you want to verify your email address in the same region that you created your app in. So if you look at the SES console up on the screen, there is a drop down where you can pick which region you want to run from. And this region should match the AWS region that you set in your application. But as you can see here, I have the same sandbox access on this account. So when you change, did you subscribe to the task first? That means you haven't configured email yet. So when it tried to send email, the application blew up. So that should stop happening as soon as we finish this exercise. So by default you have test access or sandbox access to Amazon SES. So the API will check the emails that you're sending from and that you're sending to, and requires that they are all verified by you. So in this way with a sandbox account, you can't send email to random other email addresses. So within Amazon SES, you would ask your account to be authorized to send email in production. So there's a form within SES where you can do that, and it cuts a ticket with support. Yeah, I believe you still have to verify your from address, but then you'll be able to send to anyone as long as you follow the rules associated with that. Right, so in this application, if you register an email address that you don't own, it just won't work to send email to it. As long as you've also verified the to address, if you had production access, then you can send to anyone as long as your from email is one that you own. Does that make sense? So who has gotten to the point where they've deployed with their AWS region and from email set and has validated an email address? So just a bit more than half of you, so we'll have a few more minutes for that. You had a question in the back? So have you gotten to the identity and access management step yet? So you're not gonna get emails after finishing this exercise because by default, the instance profile that we're gonna talk about next has permissions to send to absolutely nobody or to, it cannot make any API calls. It's kind of a principle of least privilege for your instances, so we're going to explicitly authorize our application server instances to make calls to Amazon SES through the SDK. So once we've finished the entire exercise two, that's when email sending will work. So if you're running into a problem that you can't identify, so the first thing if you're running into a problem is raise your hand so one of us or Trevor Lauren can come see if it's a known issue. Otherwise you would use the SSH key you created and you can SSH onto the instance and look at the Rails application logs. Emails will not work yet. After exercise 2C, they will work. So raise your hand if you've not been able to deploy the new environment variables yet. So we're gonna move on to the next exercise. So what we're gonna look at now is giving the OpsWorks IAM instance role permissions to use Amazon SES. And this is the last thing that you might be getting errors on if you've tried to send email to this point. So for a bit of background, the reason that this is necessary, remember in the beginning when we created a stack, we created IAM instance roles that were attached to each instance in your stack. And the AWS SDK can find and use that instance role as credentials. But by default, you have permissions to make absolutely no API calls. The only permissions it has is a trust relationship with OpsWorks for the OpsWorks agent to run the operations it needs to run. So any API calls you want to enable your instance to run, you have to explicitly allow. And that's what we're doing with this exercise. And then remember on this screen, I do have a screenshot for this, but you're looking for the OpsWorks EC2 role, not the OpsWorks service role. Cuz this is the role that the SDK is using to get its credentials. And then as soon as you've attached the Amazon SES full access policy, you're sending an email should work. You don't have to do a redeploy, it takes effect immediately. So once you've subscribed to task updates and changed a task state, so I may have done something wrong myself. So if I look at the EC2 role, I've applied the full access. I used the wrong email here. That is not an existing amazon.com email address. So let's try that again. Dangers of live demos. So now that is working and if I check my email, we have a task update email sent. So when you go to Amazon SES, you've verified yourself as a sender. And that should be the same email user account you sent to. So my attempt broke because I accidentally autopiloted and wrote at amazon.com instead of at gmail.com. Which is not a verified address, so it did not work. So really quickly, we have about 20 minutes left. So I'm gonna take a minute to finish some of my explanations. And then we'll be hanging around in this room and then out in the hall if we want to keep going. So I wanted to talk really quick about what we did in the application in order to configure Rails to use the SDK as a action mailer delivery method. When you require the AWS SDK Rails gem, it creates a symbol AWS underscore SDK delivery method. And that is configured to use the AWS SDK's Amazon SES client. Specifically the send raw email method as the delivery method for action mailer and that will work. And that's the only change you have to make. You do that in your configuration for any environment that you want this to work in. That in making sure your email addresses are verified and that you have permissions on your role to make this call. So there is another exercise which we don't have time for in this lab. But it doesn't take long to do, so I'd recommend checking it out. And that's configuring Ruby on Rails asset pipeline to use Amazon CloudFront as a CDN. The code change in there is really simple. We look for the asset host as the environment variable CDN domain. This is working in your deployment because right now you didn't set it, so it's nil, so it just uses your application. So if you look at your source HTML, you'll see it's pulling from the host that you're running on. So if you look at the bonus exercise and work on that, you'll end up creating a CloudFront distribution, which does take about 15 to 20 minutes, which is the reason we're not doing it now. And then you configure the CDN domain to be the domain name of the distribution you created. And then once that's set up, you'll see that the HTML is pulling your static assets from the CDN domain you've created. And we have wrote a blog post about this if you're interested. So we mentioned that we were making a few simplifications for the sake of a lab. It is worth noting that you can take this a lot further. So what I kind of diagrammed out here is a bit more of a productionized OpsWorks creation. So you could have this CloudFront CDN. You could use a product like Amazon Route 53 to set up DNS. So you can put your CloudFront distribution behind a CDN domain. And you can point other domains to parts of your application. You can use elastic load balancing to load balance across many app server instances instead of a single instance. You can set up time based auto scaling of your app server instances. So if you know that every night at midnight you get a ton of traffic. You can set that up to scale up new instances in anticipation of that traffic or load based scaling. So if you get hit really hard, new instances are created as needed. So you had a question back there? I'm sorry? So the question was what is the CDN? And that's a content distribution network. So when you use Amazon CloudFront, you can set up your application as the origin server. So Amazon CloudFront had the last time I checked. And I say that because last time I said it I was wrong and they had added more edge locations since last time I checked. They had 53 edge locations around the world. So you could be running your application server in Oregon. And you can have a person from Australia visit your website. And the static assets you have such as large images could be cached in an edge location in Australia, significantly reducing the load on your servers and the page load time. The other thing you could set up is RDS as your database. And you could have, for example, automatic fail over to a standby instance in another availability zone. So in the off chance that an entire availability zone goes down, your app can fail over and keep running. So this is what you can build. And what I hope you get out of this is that what we did build gives you the knowledge you need to keep iterating on it and build production ready systems using Amazon Web Services and Ruby on Rails. So definitely keep in touch with us. We'd love to hear your questions. We have a Ruby developer blog and we would love to hear your ideas for what you would want us to cover and what you would want us to talk about. And thank you very much.