Converted with medium-to-markdown@0.0.3
Jun 16
·5 min read
Migrate a Flask site from EC2 to S3 + CloudFront, in 7 easy steps
This compelling diagram was made by my friend Siddhant Moholanobish
This work took about 2 hours total, and saves me $14 a month!
My latest personal site was done in Flask around 2014. I had kept it running on EC2, which was free for just about a year but then started costing over $14 a month (and this is one of the smallest possible instances). In comparison, my S3 costs are only a few cents a month.
Summary of “before”:
- Flask
- EC2 (t2.micro)
- Route53 with an “A” record pointing to EC2 instance IP address
Other than costing much more money, there are other disadvantages of this setup:
- There was one year my EC2 instance kept going down, and all I’d have to do was restart it. This went away when I changed to a newer instance type, but could still start happening again.
- The EC2 instance is only in one region, and doesn’t have the performance benefits of using a distributed CDN like CloudFront
Table of Contents
- Step 1: Make your site static
- Step 2: Upload your site to S3
- Step 3: Make a CloudFront Distribution and Origin
- Step 4: Enable SSL
- Step 5: Add the Alternate Domain Name to CloudFront Distribution
- Step 6: Edit DNS “A” record in Route 53
- Step 7: Check your website
Step 1: Make your site static
My own personal site written in Python/Flask was pretty easy to migrate, since it didn’t have any direct database communication, or really anything substantial that was done on the server side, except generating the content upon startup. It had Flask templates that were fed different variables, and only a few routes, making it a perfect candidate for Frozen-Flask. Just paste their 5 or so lines of code into a “freeze.py” file (or, use any other valid name) and run
python freeze.py
.You may need to edit your original code until you’re able to run
freeze.py
without errors. For example, I had a “MimetypeMismatchWarning” which made the website not work, so I added an “html” extension to a few@app.route
annotation parameters. Overall, this step took me about 10 minutes.Step 2: Upload your site to S3
Okay, now you will need to make sure you have an AWS account, and access to it. You can use local credentials with the
aws
command line tool (installation instructions here). You also need to have a bucket. If you don’t, make one.Running
freeze.py
(see above), by default, puts everything into thebuild
directory (with anindex.html
and all of the other files/directories needed for the site), so we will upload frombuild
(or a directory of your choice).aws s3 sync build s3://mycontentsite.bizStep 3: Make a CloudFront Distribution and Origin
Follow the instructions on step 2 under “Using a REST API endpoint as the origin, with access restricted by an OAI”: https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-serve-static-website/
Note that for the above instructions:
- The origin domain is the domain of the S3 bucket you uploaded to (this is a dropdown that pre-loads with existing options). Once this is selected, the origin name will auto-populate.
- You can leave the origin path empty, unless you uploaded to a non-empty prefix
- If your bucket is not public, then you will need an “OAI” (Origin Access Identity), which is basically a user that can be added to the public policy. Letting CloudFront update the bucket policy will automatically add a block to the existing bucket policy to allow access from the OAI.
- If you already had a distribution and only created a new origin on it, then you may need to create a matching behavior. Click on the “Behaviors” tab in CloudFront, to check.
Main “Distributions” page has “Create Distribution” button
The OAI from the CloudFront distribution’s origin should match what’s in the S3 bucket policy (the blurred part)
Now, navigate to the CloudFront domain in order to check that the site is accessible and looks good. E.g. https://d2zkx5nignyw0a.cloudfront.net/
The actual work to set up a distribution and origin took about 10 minutes, but it took over 20 minutes to figure out that I was missing a CloudFront Behavior (the knowledge which came from @bax1billion).
Step 4: Enable SSL
This will basically allow “https://” to precede your domain, so that browsers don’t mark your site as “insecure”. This is important if you expect that users will be inputting information on your site.
This step may take a few hours to complete in the background, but only a minute of active work.
Navigate to Certificate Manager, and follow Step 3 on the same page as above (https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-serve-static-website/). Note that the docs don’t seem to mention Certificate Manager. It took a minute to “Request” the certificate, but a few hours before the Status became “Issued”. Make sure that your Route 53 hosted zone has a CNAME record, which should have been created when you clicked on the button to do so, when requesting the Certificate.
Certificate Manager home page
Certificate Manager will add a CNAME record matching your certificate (see blurred line). Make sure to click on the button for doing this, when requesting your certificate. This image is from the Route 53 hosted zone.
Step 5: Add the Alternate Domain Name to CloudFront Distribution
This 5 minute step is documented on https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-cloudfront-distribution.html
Go back to your CloudFront distribution and click on “Edit” next to Settings. Add an alternate domain name for your domain whose certificate you just requested (the spelling must match that in both Route 53 and the SSL certificate). Right below that field in the “Custom SSL certificate” dropdown, select the matching certificate. Make sure the name matches exactly!
Distribution Settings (Edit button)
Step 6: Edit DNS “A” record in Route 53
This takes no more than 15 minutes even if you don’t do DNS stuff regularly. Follow steps 4 through 7 in https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-cloudfront-distribution.html
Your A and AAAA records should now have the “Alias” option turned on, which creates a dropdown that includes your CloudFront distribution, which should be selected in those two records.
This is an example “A” record following the linked docs. The “AAAA” record is similar.
Step 7: Check your website
It’s time to try out your website in a browser!
- If it works, then you are done.
- If it doesn’t work, then you will need to go through the steps again!