Offloading Wordpress media from AWS EC2 to S3 via CloudFlare

Offloading Wordpress media from AWS EC2 to S3 via CloudFlare

Intro

Website performance heavily depends on the content loaded/ pulled from your server.

Running a website with lots of media files and assets will increase the number of requests to your server over time, and performance could be impacted.

On another note, cloud storage is, in theory, “unlimited” compared to a storage system you originally mapped to your EC2 instance. Some point down the line, you’ll need to expand on this.

A way to solve both these problems would be via cloud storage. Using a service such as S3 will allow you to distribute media/ content from another location, thus reducing the impact of loading all content at once from one source and pulling media from different backgrounds. Another positive to this is the ability to host your media with High Availability, thanks to the S3 service.

This will be a step-by-step guide on getting started with S3 media hosting for your WordPress website hosted on an EC2 instance.

Below is a general overview of what we’re going to create and what ducko.uk is now utilising for all future and historic media;

Cloud diagram showing how the CDN is connected

Let's get started

Pre-requisites;

  • You already have an EC2 instance set up, with access to the internet and working access to the WP dashboard.

  • AWS account permissions to allow the set up of IAM Roles, S3 buckets and amending EC2 roles.

Step 1

Create your S3 bucket and set the appropriate permissions.

Head over to S3 on your AWS dashboard.

Create a new bucket containing your domain, prefixed with “cdn”. Example: cdn.ducko.uk.

Set the permissions below when prompted and leave everything else as default (encryption, etc.).

Bucket permissions required

You can close out of S3 for now.

Step 2

We can use IAM user programmatic access (access keys) or IAM roles to delegate permissions to the EC2 instance allowing access to S3. For increased security, we will progress this example with an IAM role.

Head over to the IAM services in the AWS dashboard.

Click “Roles” on the left, and select create role on the right.

In the next window, select “AWS Service” under the “trusted entity” header and under “choose a use case”, select “EC2”.

Role creation screen

Click “Next: Permissions”.

In this window, we’re going to hit “Create Policy”.

Instead of the visual editor, we will use the JSON editor. Go ahead and select that tab.

Copy the below JSON code and input it into your JSON text box on the AWS console; changing the entries under “Resource”, where XXX is, enter your S3 bucket name we created earlier. For example, mine would be “arn:aws:s3:::cdn.ducko.uk”.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObjectAcl",
        "s3:GetObject",
        "s3:PutBucketAcl",
        "s3:ListBucket",
        "s3:DeleteObject",
        "s3:GetBucketAcl",
        "s3:GetBucketLocation",
        "s3:PutObjectAcl"
      ],
      "Resource": ["arn:aws:s3:::cdn.XXX.XXX", "arn:aws:s3:::cdn.XXX.XXX/*"]
    }
  ]
}

This role “Allows” access only to the S3 bucket you just created with the permissions of read, write, list, etc.

Follow through with the rest of the creation of the policy.

Once created, you can head back to the tab we earlier left to “Attach a permissions policy”.

Search for the policy you just created, select it, hit the button at the bottom, “Next: tags”, and follow the process until the end.

Attaching the permissions

You now have a role created and are ready for the next step.

Step 3

Time to attach the IAM Role we just created to our EC2 instance hosting our WordPress website.

That role we created is useless in its current state unless attached to an EC2 instance.

Head over to the EC2 dashboard on AWS.

Go to “Instances” on the left, select the instance you wish to apply the EC2 role too, and at the top of the screen, hit “Actions, Security, Modify IAM role”.

In the next window, you’ll be prompted to select the Role you want your EC2 instance to assume.

Select the role you just created, and select save.

You’ve now applied the role to your EC2 instance to allow it read/write access to your CDN S3 bucket.

Step 4

The next step is to install a plugin called “WP Offload Media Lite”.

Head over to your WordPress dashboard, select “plugins”, “Add New”, and search for “WP Offload Media Lite”.

Go through the usual steps to install this plugin.

In your “plugins” window, head to the plugin we just installed and select “settings”.

You’ll be prompted to select a storage option. Since we’re working with S3, select that, and the sub-option of “My server is on Amazon Web Services, and I’d like to use IAM Roles”.

Next, you’ll be asked what bucket name you want to store your media. Go ahead and enter the full name of the bucket we created earlier.

Next, we’ll head over to and log in to our Cloudflare dashboard to make some record adjustments, make the URL more SEO friendly, and for future convenience.

In your domain records, you’re going to need to create a new CNAME record that points to the S3 bucket, with the name of cdn and the content as follows;

cdn.XXX.XXX.s3-eu-west-2.amazonaws.com

You will need to replace the Xs with the remainder of your bucket name and change the S3 region to the region you created your bucket in earlier.

The result should look similar to this;

Leave it with the proxy on, and save.

Note: You may need to adjust your SSL/TLS settings to allow AWS’ SSL certificate to manage the S3 side*. Head to SSL/TLS on your Cloudflare dashboard, and select “Full”. Full allows* your Cloudflare certificate to be used on your server and other signed certificates*.*

Head back to the plugin settings on your WordPress dashboard.

You can, if you wish, use similar settings under the storage section to mine, but feel free to change up how you want this setup. There’s not much here that will break/ deviate from further steps.

In the delivery section, there will be a field saying “Provider”, which should say S3 or Cloudfront. Click "change" next to it.

You want to select “Another CDN” and " Cloudflare " in this window. Click save when complete.

We’ll move on to the “Delivery” part of the settings page.

Here, we can select different options depending on how you want to deliver your content.

Again, this will depend on you, except for the “custom domain” option. It's recommended to switch on the choices I have below.

In the “Custom Domain (CNAME)”, enter the new CNAME we created earlier, so CDN.XXX.XXX.

Upon finishing this, at the top of the page, it should give you an example URL of how it will look to your users on delivering content for your web page.

Head down to “Advanced options”.

This option will allow us to free space on our WordPress server and offload completely to S3. Go ahead and enable this.

Step 5

Testing!

Now let's test to see if everything is working as it should.

Head over to your Media tab on WordPress and select library.

Select Add new, and upload an image of your choice.

Once uploaded, select the image, and on the right in the details pane, you should have the URL for that file, and it should begin with cdn.xxx.xxx .

Copy the URL to the clipboard, pass it into your browser and see if it loads the image you just uploaded to your S3 bucket via WordPress.

You should now be viewing your WordPress image courtesy of your S3 bucket. You can also go into your S3 bucket on the AWS dashboard, and you should now start seeing objects since uploading your file to WordPress.

Note: If this didn’t work for you, you might need to recheck some items;

  • Double check the policy tied to the EC2 role (ensure the bucket name is correct)

  • Check the permissions of the bucket you created.

  • Ensure the URL set in Cloudflare is correct

  • Go back through the plugin settings to ensure everything is correct.

If you’re using other DNS providers, or want to use Cloudfront, the plugin provider provides instructions here to suit those requirements.

You're done!

That’s it.

Sit back and relax, knowing all your content is now highly available, highly redundant and freeing up your instance/ server for serving your users for years to come more speedily.

If you have any issues with this, please let me know in the comments below.

Thanks for reading!

Did you find this article valuable?

Support Daniel Jones by becoming a sponsor. Any amount is appreciated!