Tech AI Insights

Laravel S3 CloudFront Image Upload: 7 Proven Steps for Fast, Secure, Keyless Setup

Introduction

Laravel S3 CloudFront image upload is one of the best ways to manage image storage and delivery in modern web applications. It gives you the ability to securely upload images to AWS S3 and serve them globally through CloudFront—without exposing sensitive access keys in your Laravel project.

Whether you’re building a SaaS app, a content-heavy CMS, or an e-commerce platform, this setup ensures performance, security, and scalability.

Handling file uploads in Laravel is common, but doing it right—with security, performance, and scalability—requires a smart setup. This is where the Laravel S3 CloudFront image upload strategy comes in.

In this guide, you’ll learn exactly how to upload images securely from a Laravel app to AWS S3 and serve them blazing fast using CloudFront—without ever storing access keys in your .env file. Whether you’re launching a SaaS, portfolio, or e-commerce platform, this method keeps your app secure and production-ready.

Why Use Laravel + S3 + CloudFront?

Before we dive in, here’s why this setup is worth it:

  • Secure: No access keys are stored locally—Laravel uses EC2’s IAM role.
  • Scalable: S3 handles massive amounts of files without slowing down.
  • Fast: CloudFront serves your images globally using AWS edge locations.
  • Effortless DevOps: No key rotation or manual permission headaches.

Step 1: Create an S3 Bucket

This bucket is where your Laravel app will store uploaded images.

  • Go to the AWS Console → S3 → Create bucket.
  • Set a unique bucket name (e.g., my-laravel-app-images).
  • Uncheck “Block all public access” — we’ll restrict access via CloudFront.
  • (Optional) Enable versioning to keep previous file versions.
  • Click Create Bucket.

Done! Now, we give Laravel permission to write to this bucket.

Step 2: Create an IAM Role for EC2 Access to S3

To securely connect Laravel to S3:

  • Go to IAM → Roles → Create role.
  • Choose AWS Service → EC2.
  • Attach a custom policy like this:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::my-laravel-app-images/*"
    }
  ]
}
  • Name your role LaravelS3AccessRole.
  • Attach it to your EC2 instance via Actions → Security → Modify IAM Role.

Step 3: Configure Laravel to Use S3 (Without Keys)

Laravel will now use EC2’s IAM role to talk to AWS.

Update your .env:

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=my-laravel-app-images
AWS_URL=https://your-cloudfront-url.cloudfront.net

Keep the access key fields empty.

In config/filesystems.php:

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => false,
],

Step 4: Create a CloudFront Distribution

Let’s now serve those images worldwide.

  • Go to CloudFront → Create Distribution.
  • Under Origin Domain, choose your S3 bucket.
  • Create an Origin Access Control (OAC) and set it to sign requests.
  • Viewer protocol policy: Redirect HTTP to HTTPS.
  • Click Create and copy the CloudFront domain (e.g., d1234abc.cloudfront.net).

Step 5: Update the S3 Bucket Policy for CloudFront

CloudFront needs permission to read from your bucket.

In S3 → Bucket → Permissions → Bucket Policy, add:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontReadAccess",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-laravel-app-images/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::YOUR_ACCOUNT_ID:distribution/YOUR_DIST_ID"
        }
      }
    }
  ]
}

Replace placeholders with your real account and distribution ID.

Step 6: Upload Images in Laravel

Here’s a simple controller method for uploads:

public function upload(Request $request)
{
    $path = Storage::disk('s3')->put('images', $request->file('image'));
    $url = Storage::disk('s3')->url($path);
    return response()->json(['url' => $url]);
}

If your AWS_URL is set, the returned URL will point to CloudFront.

Step 7: Test the Integration

Upload a test image and check:

  • ✅ Appears in S3
  • ✅ CloudFront URL loads quickly
  • ✅ URL is private (not public on S3)

That’s it—you’ve completed a secure, access-key-free Laravel S3 CloudFront image upload setup.

Recap: Why This Setup Works

Tool Purpose
IAM Role Secure access to S3 without exposing keys
S3 Stores images securely and at scale
CloudFront Global CDN for faster image delivery
Laravel Config Seamless integration without secrets

Summary

Setting up a Laravel S3 CloudFront image upload system without access keys may seem complex at first—but once configured, it’s faster, safer, and production-ready. You get secure uploads, global delivery, and no headaches from managing credentials.

For more insightful tutorials, visit our Tech Blogs and explore the latest in Laravel, AI, and Vue.js development!

Scroll to Top