Setup AWS S3 for Laravel Storage

Setup AWS S3 for Laravel Storage

Prerequisites

  1. Active AWS Account

  2. Laravel Project

The S3 package

composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies

The Access

IAM User Group

  1. In the search bar at the top, type "IAM" and click on the IAM service.

  2. On the left sidebar, click "User Groups"

  3. Click the "Create group" button

  4. Create a name for the group, I am going to call mine "S3Access", all the users in this group will have full access to do anything to any of my S3 buckets, but they will ONLY have access to make changes to S3 buckets.

  5. Scroll down and in the Attach permissions policies, search for "S3". The search bar here is a bit wonky, just hit enter and you will see the list update.

  6. Check the box next to "AmazonS3FullAccess" and click the "Create group" button on the bottom.

IAM User

  1. Next click "Users" in the left sidebar.

  2. Click "Create user" and give the user a name. Now the name can be anything you want, typically I make a user for each of my apps and name it accordingly.

  3. DO NOT check the box to grant the user AWS Console access unless you know what you are doing. Essentially, this will also allow our user to log into AWS and also have API access which isn't the goal of this demo.

  4. Click "Next". Now we are going to add this user to the group we just made, check the box next to the group and click "Next".

  5. You can add "Tags" to your user if you want, I normally just skip these. Click "Create user".

Access Key and Secret

  1. The next screen should show you a list of all your users, click on the user you just created.

  2. Click on the Security credentials tab and scroll down to the "Access keys" section.

  3. Click "Create access key".

  4. For this tutorial, the user we are creating is essentially a "Third-party service", select it, check the Confirmation at the bottom and click "Next".

  5. I skip the description tag. Each user can have multiple access key (up to 2) and you can label them here if you want.

  6. Click "Create access key". On the next page you will see your access key, and you can show or copy your secrete access key. You will need both of these values, copy them and paste them into your Laravel .env file.

THE BUCKET

Create the Bucket

  1. In the search bar type "s3" and select "S3".

  2. Click the "Create bucket" button. On the next screen we are going to specify several things that you can edit later, except the bucket name.

  3. Additionally, be sure to take note of the "AWS Region", you will need this in your .env.

  1. Scroll down and check the "ACLs enabled" radio button in the "Object ownership" section.

  2. Select "Object writer".

  3. Uncheck the "Block all public access" and check the acknowledgement.

  4. I will keep versioning disabled, no tags... I will leave the rest of the defaults untouched and click "Create bucket".

Update Bucket Policy and CORS

  1. The next screen should be a list of your buckets, click on the one you just created.

  2. Click the "Permissions" tab.

  3. In the "Bucket policy" section click the "Edit" button, paste the following code, but make sure you update YOUR_BUCKET_NAME with your bucket's name and click "Save changes".

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
    ]
}
  1. You can read more on how to control who and what has access to your bucket objects, this statement will allow any "Principal" or entity to take any action in our bucket. You can get more strict with statements like this as you learn more.

  2. Scroll to the "Access control list (ACL)" section and click the "Edit" button.

  3. Check the box for "List" and "Read" next to "Everyone (public access)" and check the acknowledgement on the bottom and click "Save changes".

  4. Scroll down to the "Cross-origin resource sharing (CORS)" section, click the "Edit" button and paste in the following code:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "x-amz-server-side-encryption",
            "x-amz-request-id",
            "x-amz-id-2"
        ],
        "MaxAgeSeconds": 3000
    }
]
  1. In the "AllowedOrigins" section of that json we are allowing ALL origins, that means ANY domain can access the objects in this bucket. If you want to limit that to a specific domain you can adjust it here.

  2. Click on the "Objects" tab. we will refresh this section once we push some objects to the bucket.

  3. Let's head back over to the Laravel app and update our .env accordingly, set your bucket name, region, url, etc. like this.

AWS_ACCESS_KEY_ID=AKIA...TBHAKB
AWS_SECRET_ACCESS_KEY=WaVKTJ...eeLwnf/CMZR0w...GKn8e
AWS_DEFAULT_REGION=YOUR_REGION
AWS_BUCKET=YOUR_BUCKET_NAME
AWS_URL="https://YOUR_BUCKET_NAME.s3.YOUR_REGION.amazonaws.com/"
AWS_USE_PATH_STYLE_ENDPOINT=true

Set Storage Disk

FILESYSTEM_DISK=s3

Disclaimer

I’ve followed https://laravel-news.com/using-aws-s3-for-laravel-storage and updated some parts of Policy and CORS