Using a cloud stor­age sys­tem like AWS S3 with a CDN dis­tri­b­u­tion can be a con­ve­nient and inex­pen­sive way to store your assets. Here’s how to set it up right.

Assets like images, PDFs, and oth­er files are often an impor­tant part of the “con­tent” that a Con­tent Man­age­ment Sys­tem handles.

Although this arti­cle was writ­ten with Craft CMS in mind, the vast major­i­ty of the arti­cle applies gener­i­cal­ly to any CMS or website.

Craft CMS has some fan­tas­tic native han­dling of said assets, which by default are stored in fold­ers on your server.

How­ev­er, it can be con­ve­nient to use a cloud-based stor­age sys­tem like Ama­zon Web Ser­vices (AWS) Sim­ple Stor­age Ser­vice (S3):

  • You’ll nev­er run out of disk space
  • Your assets are inher­ent­ly backed up & stored off-site
  • Your assets can go to long-term back­up in AWS Glac­i­er easily
  • You can lever­age a Con­tent Deliv­ery Net­work (CDN) in the form of Cloud­front
  • Elim­i­nates the need to sync assets between local dev, stag­ing, and pro­duc­tion environments
  • It’s cheap (or even free) & scalable

There are oth­er advan­tages as well, but we’ll just assume you’re on-board, and get right into how to set it up.

LINKSETTING UP S3

S3 stores files in “buck­ets”, and while you can serve assets direct­ly from an S3 buck­et, I’d strong­ly rec­om­mend against it.

Don’t serve assets directly from S3 buckets

S3 buck­ets are intend­ed for asset stor­age, not serv­ing assets. It’ll work, but you’ll only be serv­ing them out of one geo­graph­ic region (wher­ev­er your S3 buck­et was cre­at­ed), and it real­ly was­n’t designed to for that.

Instead, use AWS Cloud­Front as your Con­tent Deliv­ery Net­work (CDN) that actu­al­ly serves up your assets.

Here’s what it looks like conceptually:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KjGgikUB-1669738403971)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAANABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAwAG%2F8QAIBAAAgIBBAMBAAAAAAAAAAAAAQIDBAAREjFRExQhcf%2FEABUBAQEAAAAAAAAAAAAAAAAAAAAB%2F8QAGhEAAgMBAQAAAAAAAAAAAAAAAQIAETESIf%2FaAAwDAQACEQMRAD8A1lxoblSREsqgVgGYHg9ZQv6lWvGh84Ztu%2FcBz%2B4y0ayo6rCoVzqw7OFZrqqwLGEVVkHwrrlJN%2BZCIt9Ns%2F%2FZ)]

AWS S3 + Cloud­Front Overview

The idea is that when a per­son loads one of your web pages with an image on it, the image will point to a Cloud­Front URL.

If that image is in the cache, it’ll return it from a CDN Edge serv­er that is geo­graph­i­cal­ly near the per­son load­ing the page. This makes it quick, with low latency.

If the image isn’t in the cache, Cloud­Front pulls it from your S3 buck­et, returns it to the per­son, and prop­a­gates the image to the CDN Edge locations.

S3 Buckets shouldn’t be publicly accessible

The rule of thumb here is that S3 buck­ets aren’t pub­licly acces­si­ble. Instead, Cloud­Front is giv­en per­mis­sion to pull assets from the S3 buckets.

That said, let’s get into set­ting it all up.

LINKSTEP 1: HAVE AN AWS ACCOUNT

If you don’t already have an AWS account, you’re going to need one. Go to your AWS Con­sole and either log in to your account, or cre­ate a new account.

If you want the billing to go direct­ly to your clients, you can either cre­ate an AWS account for them, or use their exist­ing account.

If you fac­tor in the rel­a­tive­ly low cost of S3 into your main­te­nance con­tracts or the like, you can just have one account for all of your clients.

If you don’t have one already, you should also set up an admin account for AWS now.

LINKSTEP 2: CREATE AN S3 BUCKET

Now that we have an AWS account, the first thing we’re going to do is set up our S3 buck­et. We’re going to use kebab-case for all of our AWS enti­ty names, and we’ll use the format:

project-name + - + descriptor

We’ll be set­ting up S3 + Cloud­Front for devMode.fm, so the project name is devmode, and the buck­et name is devmode-bucket.

In your AWS Con­sole, click on Ser­vices → S3 → + Cre­ate Buck­et. Fill in the name of the buck­et, and click through to the end (we won’t be chang­ing any set­tings from the default oth­er than the name):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pAgYlftu-1669738403978)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAALABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAgAD%2F8QAIBAAAQMCBwAAAAAAAAAAAAAAAQACAwRBERITITFRgf%2FEABQBAQAAAAAAAAAAAAAAAAAAAAP%2FxAAXEQADAQAAAAAAAAAAAAAAAAAAARJR%2F9oADAMBAAIRAxEAPwDF9VMN9SyLauYuGLzz0hYKaBn9CanoMrD%2F2Q%3D%3D)]

Cre­at­ing an S3 bucket

Note that for Per­mis­sions, it’s set to Block *all* pub­lic access. As dis­cussed above, our S3 buck­et will be pri­vate, and the Cloud­Front dis­tri­b­u­tion will be public.

For most projects, I cre­ate one buck­et, and use sub-fold­ers in the buck­et for dif­fer­ent Asset Vol­umes. You can cer­tain­ly also cre­ate more than one buck­et if that’ll work bet­ter for you.

LINKSTEP 3: CREATE A CUSTOM POLICY

Next we’ll set up a cus­tom Iden­ti­ty and Access Man­age­ment (IAM) pol­i­cy to con­trol access. IAM poli­cies can be attached to any AWS object, and they con­trol who can access what, with some fair­ly fine-grained permissions.

We’re using a cus­tom pol­i­cy because we want to grant as lit­tle access as pos­si­ble, but still have it work correctly.

This isn’t a fancy watch. We don’t add complications just because they look cool

From your AWS Con­sole, click on Ser­vices → IAM → Poli­cies → Cre­ate Pol­i­cy.

Click on the JSON tab, and then paste this in:

custom policy

{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["acm:ListCertificates","cloudfront:GetDistribution","cloudfront:GetStreamingDistribution","cloudfront:GetDistributionConfig","cloudfront:ListDistributions","cloudfront:ListCloudFrontOriginAccessIdentities","cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","elasticloadbalancing:DescribeLoadBalancers","iam:ListServerCertificates","sns:ListSubscriptionsByTopic","sns:ListTopics","waf:GetWebACL","waf:ListWebACLs"],"Resource": "*"},{"Effect": "Allow","Action": ["s3:GetBucketLocation","s3:ListAllMyBuckets"],"Resource": "*"},{"Effect": "Allow","Action": ["s3:ListBucket"],"Resource": ["arn:aws:s3:::REPLACE-WITH-BUCKET-NAME"]},{"Effect": "Allow","Action": ["s3:*"],"Resource": ["arn:aws:s3:::REPLACE-WITH-BUCKET-NAME/*"]}]
}

custom policy

Make sure you replace REPLACE-WITH-BUCKET-NAME with the name of the buck­et we cre­at­ed in Step 2 (in our case devmode-bucket), in both places.

Then click on Review Pol­i­cy, and give your pol­i­cy a name (in our case devmode-policy) and descrip­tion, then click on Cre­ate Pol­i­cy:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCTGlRcL-1669738403989)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAALABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAQIG%2F8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAEQMhEhNh%2F8QAFAEBAAAAAAAAAAAAAAAAAAAAAP%2FEABQRAQAAAAAAAAAAAAAAAAAAAAD%2F2gAMAwEAAhEDEQA%2FAN2zcWoXHsB0VO%2FInYBkZmKJamjA%2F9k%3D)]

Cre­at­ing an IAM policy

LINKSTEP 4: CREATE A GROUP

Instead of attach­ing the IAM pol­i­cy we cre­at­ed to a buck­et or a user, we’re going to cre­ate a group, and attach it to the group.

The IAM policy gets attached to the group

We’re doing this because it makes it triv­ial to move users in and out of the group, and the group is what is con­trol­ling access permissions.

You also then won’t be out of luck if you some­how lose the user cre­den­tials, you can just cre­ate a new user and assign it to the group.

From your AWS Con­sole, click on Ser­vices → IAM → Groups → Cre­ate New Group, and give your group a name (in our case devmode-group).

At the Attach Pol­i­cy screen, search for the pol­i­cy we cre­at­ed in Step 3, and check it and click Next Step:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ap9EFMJr-1669738403991)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAAKABADASIAAhEBAxEB%2F8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBv%2FEABkQAQEBAAMAAAAAAAAAAAAAAAEAAxJRYf%2FEABQBAQAAAAAAAAAAAAAAAAAAAAD%2FxAAUEQEAAAAAAAAAAAAAAAAAAAAA%2F9oADAMBAAIRAxEAPwDfcTqcU91MlFHyD%2F%2FZ)]

Cre­at­ing a group

Then click on Cre­ate Group to cre­ate your new group.

LINKSTEP 5: CREATE A USER

Next we’re going to cre­ate a user, and assign it to the group we just cre­at­ed. The user we cre­ate will be a gener­ic project user, rather than an actu­al person.

From your AWS Con­sole, click on Ser­vices → IAM → Users → Add user, and give your user a name (in our case devmode-user). Also check only the Pro­gra­mat­ic access check­box under Access type:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZioFDGZF-1669738403993)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAANABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAgEG%2F8QAGhABAAIDAQAAAAAAAAAAAAAAAQACESFBMf%2FEABQBAQAAAAAAAAAAAAAAAAAAAAD%2FxAAUEQEAAAAAAAAAAAAAAAAAAAAA%2F9oADAMBAAIRAxEAPwDdq044zzcVUXzcckD%2F2Q%3D%3D)]

Cre­at­ing a user: details

This ensures that using these cre­den­tials, there’s no AWS Man­age­ment Con­sole access. For that, you’ll use your reg­u­lar admin account & credentials.

Click on Next: Per­mis­sions, then add the user to the group we cre­at­ed in Step 4:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8hiE5LvU-1669738404009)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAANABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAQMG%2F8QAGxABAAMBAAMAAAAAAAAAAAAAAQACESExUYH%2FxAAUAQEAAAAAAAAAAAAAAAAAAAAA%2F8QAFBEBAAAAAAAAAAAAAAAAAAAAAP%2FaAAwDAQACEQMRAD8A3NVN21vPqJc49fkoW1TIwP%2FZ)]

Cre­at­ing a user: permissions

Then click on Next: Tags (we don’t set any tags here), then click on Next: Review:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o5JJki9R-1669738404012)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAANABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAgAG%2F8QAGxAAAwACAwAAAAAAAAAAAAAAAAERITFBcYH%2FxAAUAQEAAAAAAAAAAAAAAAAAAAAA%2F8QAFBEBAAAAAAAAAAAAAAAAAAAAAP%2FaAAwDAQACEQMRAD8A3absVnQsc1%2BC0QH%2F2Q%3D%3D)]

Cre­at­ing a user: review

Then click on Cre­ate User. You’ll be tak­en to a screen where you can see your Access key ID and Secret access key:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ia2gZTfC-1669738404018)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAAGABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAAIG%2F8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAAxEiMSH%2FxAAUAQEAAAAAAAAAAAAAAAAAAAAA%2F8QAFBEBAAAAAAAAAAAAAAAAAAAAAP%2FaAAwDAQACEQMRAD8A3IJydiPeSEvV7Gr2JU4OeRED%2F9k%3D)]

Cre­at­ing a user: credentials

Click on Down­load .csv to down­load a CSV file that has your cre­den­tials in it. You will need these cre­den­tials to access your S3 buck­et, and this is the only time you’ll be able to retrieve them.**
**

LINKSTEP 6: CREATE A CLOUDFRONT DISTRIBUTION

Now we need to cre­ate a Cloud­Front Dis­tri­b­u­tion that will be act­ing as our CDN, and actu­al­ly deliv­er­ing our assets to the users who request them.

From your AWS Con­sole, click on Ser­vices → Cloud­Front → Cre­ate Dis­tri­b­u­tion, and click on the Get Start­ed but­ton below the Web heading.

Alter the fol­low­ing settings:

  • Ori­gin domain — choose the ori­gin for the S3 buck­et we cre­at­ed in Step 2

  • S3 buck­et access

    • select

      Yes use OAI (buck­et can restrict access to only CloudFront)

      • click Cre­ate New OAI, give it a name, save it, select it
    • Buck­et pol­i­cy

      • select Yes, update the buck­et policy
  • Com­press object automatically

    • select Yes
  • View­er Pro­to­col Pol­i­cy — Redi­rect HTTP to HTTPS

  • Allowed HTTP Meth­ods — GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE

  • Cache key and ori­gin requests

    • select

      Cache pol­i­cy and ori­gin request pol­i­cy

      (rec­om­mend­ed)

      • Cache pol­i­cy

        • select Cachin­gOp­ti­mized

N.B.: For your buck­et to work with Cloud­Front, the name must con­form to DNS nam­ing require­ments. For Regions launched in 2019 or lat­er, that for­mat is: bucket-name.s3.region.amazonaws.com

Here’s a full screen­shot for the set­tings we’re using for devMode.fm:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jQcHpd9k-1669738404024)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQEAYABgAAD%2F%2FgA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2ODApLCBxdWFsaXR5ID0gNTAK%2F9sAQwAQCwwODAoQDg0OEhEQExgoGhgWFhgxIyUdKDozPTw5Mzg3QEhcTkBEV0U3OFBtUVdfYmdoZz5NcXlwZHhcZWdj%2F9sAQwEREhIYFRgvGhovY0I4QmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nj%2F8AAEQgALQAQAwEiAAIRAQMRAf%2FEAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC%2F%2FEALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29%2Fj5%2Bv%2FEAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC%2F%2FEALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5%2Bjp6vLz9PX29%2Fj5%2Bv%2FaAAwDAQACEQMRAD8A7mNQCcKv4DmpNo9KiVfmOPX1%2FwDr1NzjqKAGRnqAD%2BdP59P1pkTdQT0PFSHpQBChO4jI69OalFMReSePyp9AH%2F%2FZ)]

Cre­at­ing a Cloud­Front Distribution

Then click on Cre­ate Dis­tri­b­u­tion.

You’ll be tak­en to a strange “Cloud­Front Pri­vate Con­tent Get­ting Start­ed” page; this isn’t an error page, and there aren’t any more steps to take.

We just need to grab a cou­ple of set­tings from our new­ly cre­at­ed Cloud­Front distribution.

From your AWS Con­sole, click on Ser­vices → Cloud­Front → then click on the Cloud­Front dis­tri­b­u­tion we just created:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVPtpKKF-1669738404028)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAAKABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAAAgMG%2F8QAHhAAAQQCAwEAAAAAAAAAAAAAAQACAxESIQQyYXH%2FxAAUAQEAAAAAAAAAAAAAAAAAAAAA%2F8QAFBEBAAAAAAAAAAAAAAAAAAAAAP%2FaAAwDAQACEQMRAD8A3E5EeOJok7KcdOFh2XtockbZ9Vm9Qg%2F%2F2Q%3D%3D)]

Cloud­Front Dis­tri­b­u­tion Settings

We’re going to need the Dis­tri­b­u­tion ID and Domain Name set­tings, so copy them down somewhere.

We’re all done with the AWS S3 + Cloud­Front setup!

LINKSTEP 7: CONFIGURE YOUR ASSET VOLUMES IN CRAFT CMS

Next we need to con­fig­ure Craft CMS to use our new S3 buck­et set­up. If you’re using some­thing oth­er than Craft CMS, you’ll need to fill in the anal­o­gous settings.

The key point to remem­ber is that the pub­lic URL will be our Cloud­Front dis­tri­b­u­tion URL (in our case https://dnzwsrj1eic0g.cloudfront.net); make sure you add the https:// pro­to­col to it.

First, we’ll need to install the first-par­ty Ama­zon S3 plu­g­in.

Next we’ll need to set up our Asset Vol­umes. I use Envi­ron­ment Vari­ables in my .env file to store all of my secrets, so they aren’t in the data­base, and the don’t end up in Git via Project Con­fig:

.env file environment variables

# S3 settings
S3_KEY_ID=XXXXXXXXXX
S3_SECRET=XXXXXXXXXX
S3_BUCKET=devmode-bucket
S3_REGION=us-east-2# CloudFront settings
CLOUDFRONT_URL=https://dnzwsrj1eic0g.cloudfront.net
CLOUDFRONT_DISTRIBUTION_ID=E17SKV1U1OTZKW
CLOUDFRONT_PATH_PREFIX=

.env file environment variables

In the Craft CMS CP, go to Set­tings → Assets → New vol­ume, and fill in the vol­ume set­tings as shown:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0aOZa6xg-1669738404033)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAHAAcAAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAAbABADASIAAhEBAxEB%2F8QAFwABAAMAAAAAAAAAAAAAAAAAAgEDBv%2FEABwQAAICAgMAAAAAAAAAAAAAAAABAgMRMTJBgf%2FEABQBAQAAAAAAAAAAAAAAAAAAAAD%2FxAAUEQEAAAAAAAAAAAAAAAAAAAAA%2F9oADAMBAAIRAxEAPwDdQrjjQnVFrDRMOOxIAQ8GV19jA%2F%2FZ)]

Craft CMS Asset Vol­ume settings

Note that Buck­et has been set to Man­u­al so we can use our envi­ron­ment vari­ables, and we’ve man­u­al­ly added episodes to Sub­fold­er.

Also note that we have turned Make Uploads Pub­lic OFF. If you enable it, it will set a man­u­al ACL on your S3 assets to allow pub­lic access, which isn’t what we want. We want pri­vate S3 assets with pub­lic access through Cloud­Front only

If you’re using Project Con­fig, your project.yaml will end up look­ing like the following:

project.yaml

  e69c8edb-d562-4367-9a05-91a6fd2c7d99:name: 'Devmode Episodes'handle: devmodeEpisodestype: craft\awss3\VolumehasUrls: trueurl: $CLOUDFRONT_URLsettings:subfolder: episodeskeyId: $S3_KEY_IDsecret: $S3_SECRETbucketSelectionMode: manualbucket: $S3_BUCKETregion: $S3_REGIONexpires: '3 months'makeUploadsPublic: ''storageClass: ''cfDistributionId: $CLOUDFRONT_DISTRIBUTION_IDcfPrefix: $CLOUDFRONT_PATH_PREFIXautoFocalPoint: ''sortOrder: 4

project.yaml

Look, mah, no secrets!

Then we can upload an image to our new Asset Volume:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0fiIRer-1669738404045)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAALABADASIAAhEBAxEB%2F8QAFgABAQEAAAAAAAAAAAAAAAAABQQH%2F8QAIxAAAgIBAgYDAAAAAAAAAAAAAQIDBAUAEgYREyFhcRRBUf%2FEABUBAQEAAAAAAAAAAAAAAAAAAAAB%2F8QAFREBAQAAAAAAAAAAAAAAAAAAAAH%2F2gAMAwEAAhEDEQA%2FAEeC1%2BZj5DOkcuwqqlgOw2%2BtN5KjAMbaIgiBETnmFH4fGs1wubyNGu6VbJjUkEjYp%2BvI1bY4mzEleRHuEqykEdNe45etWj%2F%2F2Q%3D%3D)]

Uploaded Image in the Craft CMS CP

And we can ver­i­fy that the image is indeed com­ing from our Cloud­Front dis­tri­b­u­tion URL:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nz8YSmL4-1669738404049)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQIAOQA5AAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAANABADASIAAhEBAxEB%2F8QAFwAAAwEAAAAAAAAAAAAAAAAAAQIFBv%2FEACEQAAIBBAICAwAAAAAAAAAAAAIDAQAEESEFBhJBEyIx%2F8QAFAEBAAAAAAAAAAAAAAAAAAAAAP%2FEABQRAQAAAAAAAAAAAAAAAAAAAAD%2F2gAMAwEAAhEDEQA%2FAJ3XXOu7eYZiRXgYkVjqMe9U3ZXMtLZfwNEgcOC8kjExrfqs%2FwAfy7rBRrVGjn7b%2FaPIcu6%2FStbRGBXGBxQf%2F9k%3D)]

Uploaded Image Cloud­Front dis­tri­b­u­tion URL

LINKFILL YOUR BUCKETS

That’s all you need to start enjoy­ing the ben­e­fits of cloud stor­age in S3, and Cloud­Front as a glob­al Con­tent Deliv­ery Network.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QWvRKv9E-1669738404053)(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P%2F2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P%2FwAARCAAJABADASIAAhEBAxEB%2F8QAFQABAQAAAAAAAAAAAAAAAAAAAgX%2FxAAjEAACAgEACwAAAAAAAAAAAAABAwIEABESExQiMTJBUWFx%2F8QAFQEBAQAAAAAAAAAAAAAAAAAABAX%2FxAAcEQABBAMBAAAAAAAAAAAAAAARAAECEwMEIeH%2F2gAMAwEAAhEDEQA%2FAKD1XC5a6yxokDrSPKPg4aqrh229rEBE8PvLKu2G10n6MkUwbXI76ntllaCv%2F9k%3D)]

This whole man­u­al set­up can be auto­mat­ed via an AWS Cloud­For­ma­tion stack… but that’s left as an exer­cise for the read­er (or maybe anoth­er article).

Thanks to all around great guy Jonathan Melville of CodeMDD.io for this help with this article.

Hap­py uploading!

FURTHER READING

  • Setting Up Your Own Image Transform Service
  • Creating a Reverse Proxy for Partytown with AWS Cloudfront
  • Post-Mortem: Applied Image Optimization

using-aws-s3-buckets-cloudfront-distribution-with-craft-cms相关推荐

  1. aws s3 静态网站_如何使用AWS S3,CloudFront和命令行管理静态网站

    aws s3 静态网站 by Ben Cheng 通过本诚 如何使用AWS S3,CloudFront和命令行管理静态网站 (How to manage your static websites wi ...

  2. AWS: S3+Lambda+CloudFront的使用(CDK)

    一.简介 AWS CloudFront 是一项快速内容分发网络 (CDN) 服务,可以安全地以低延迟和高传输速度向全球客户分发数据.视频.应用程序和 API,全部都在开发人员友好的环境中完成.例如:当 ...

  3. aws s3 静态网站_如何将静态网站或JAMstack应用托管并部署到AWS S3和CloudFront

    aws s3 静态网站 S3 and CloudFront are AWS cloud services that make serving static assets powerful and ch ...

  4. aws s3及cloudfront访问问题

    1:s3加cdn及ec2加负载均衡后,每次解析的ip会不同,导致有些解析后的ip网络不通,导致接口及图片访问不了 2:偶尔出现无法解析的问题,或者解析时间过长(域名解析商dnspod国际版) 3:访问 ...

  5. aws s3 静态网站_使用AWS S3存储桶启动静态网站

    aws s3 静态网站 This article explores the AWS S3 bucket to configure a static website. 本文探讨了用于配置静态网站的AWS ...

  6. aws rds监控慢sql_将AWS S3存储桶与AWS RDS SQL Server集成

    aws rds监控慢sql This article gives you an overview of integrating AWS S3 buckets with AWS RDS SQL Serv ...

  7. aws s3 cli_了解AWS CLI –使用AWS CLI与AWS S3存储桶进行交互

    aws s3 cli It is the second article in the Learn AWS CLI series. It gives you an overview of working ...

  8. cloudfront s3_如何使用S3,CloudFront和Route53托管静态网站

    cloudfront s3 by Paul Berg 保罗·伯格 如何使用S3,CloudFront和Route53托管静态网站 (How to Host a Static Website with ...

  9. 通过亚马逊云科技实现基于 Restful API 的 CloudFront Distribution 复制/克隆功能

    背景 Amazon CloudFront 是一个全球性的内容分发网络 (CDN),您可以借助 CloudFront 以低延迟和高可用性向查看者或者最终用户分发内容.通常来讲,Amazon CloudF ...

  10. aws s3 参与s3game寻找宝藏游戏挑战学习s3对象存储

    参考资料 Pirates S3game workshop http://s3game-level1.s3-website.us-east-2.amazonaws.com/level1.html htt ...

最新文章

  1. UnicodeEncodeError: 'ascii' codec can't encode character....
  2. Science:细胞如何测量自身的大小?答案是:DNA含量
  3. VR/AR标准委员会成立,宣布全新的标准OpenXR
  4. Scala教程之:可变和不变集合
  5. matlab如何使用cu文件,Matlab编译cuda的.cu文件
  6. archlinux php mysql,arch linux上安装 httpd+php+mysql+ openssl(转)
  7. C#枚举类型用户标志位的代码
  8. [转载] Python的双端队列deque
  9. 1.1 文本表示——离散形式表示
  10. python获取线程返回值_如何从python中的线程获取返回值?
  11. 怎么用vc采集ni卡数据_「解决方案」三维激光扫描多数据混合作业,助力“地籍调查”...
  12. 阿铭Linux_网站维护学习笔记20190415
  13. mac top内存 cpu
  14. 利用Xenu查询网站死链
  15. string.class是什么意思?
  16. Win11十二月系统更新了什么内容?
  17. 电子商务项目设计(案例)
  18. Unicode blocks 统计
  19. 华为5c_华为5c手机价格及产品参数配置【图文】
  20. Jason和xml两者的区别

热门文章

  1. PTA 7-33 统计素数并求和
  2. 电力拖动与控制系统 第二讲笔记
  3. 同时使用IP代理池和用户代理池(做笔记)
  4. 关于msn登陆不上去了的解决方法
  5. 计算机中cmos设置程序,计算机CMOS设置详解.doc
  6. 计算机是一种能够预先,第1章计算机基础知识 一级msoffice电子教案
  7. 10_libpcap以及libnet
  8. 这几个CNAD领域对实验人员的要求,赶紧收藏
  9. 常用芯片型号功能汇总
  10. html酷炫电子时钟效果,逼真的HTML5 canvas模拟时钟特效