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!