Post

Why You Should Use External Storage Buckets For Your Files

Explore the benefits of using external storage solutions like Cloudflare R2 for file management in Laravel applications and how to implement them effectively.

Why You Should Use External Storage Buckets For Your Files

When developing modern web applications, especially those that handle user-uploaded content, choosing the right file storage solution is crucial for performance, scalability, and cost efficiency. While Laravel makes it easy to store files locally, external storage solutions like Cloudflare R2, AWS S3, or Google Cloud Storage offer significant advantages that can benefit your application in the long run.

Benefits of External Storage Solutions

šŸš€ 1. Scalability

  • Handle unlimited files without worrying about server disk space limitations
  • Scale your application without being constrained by local storage capacity
  • Accommodate growing user bases and increasing file storage requirements with ease

šŸŒ 2. High Availability

  • Files remain accessible even if your application server experiences downtime
  • Built-in redundancy ensures your data is replicated across multiple locations
  • Most cloud providers offer 99.9%+ uptime guarantees for their storage services

⚔ 3. Performance Optimization

  • Offload file delivery to specialized content delivery networks (CDNs)
  • Reduce the load on your application server by separating storage concerns
  • Files are served from edge locations closest to your users for faster download times

šŸ” 4. Enhanced Security

  • Take advantage of advanced security features like:
    • Signed URLs for time-limited access
    • Fine-grained access policies
    • Encryption at rest and in transit
    • Protection against unauthorized access

šŸ’µ 5. Cost Efficiency

  • Pay only for what you use with flexible pricing models
  • Eliminate the need for expensive disk space on application servers
  • Some providers (like Cloudflare R2) offer no egress fees, reducing costs for applications with high download volumes

🧩 6. Better Architecture

  • Separation of concerns: application logic remains distinct from file storage
  • Ideal for multi-server setups and containerized applications
  • Simplifies deployment processes and server maintenance

Implementing Cloudflare R2 in Laravel

Cloudflare R2 has become a popular choice for Laravel applications due to its S3 compatibility, zero egress fees, and integration with Cloudflare’s global CDN. Here’s how to set it up:

1. Install the S3 Filesystem Driver

Cloudflare R2 works with Laravel’s S3 driver, so you’ll need to install the required package:

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

2. Configure a New Disk

Update your config/filesystems.php file to include a new R2 disk configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'disks' => [
    // ... existing disk configurations

    'r2' => [
         'driver' => 's3',
         'key' => env('CLOUDFLARE_R2_ACCESS_KEY_ID'),
         'secret' => env('CLOUDFLARE_R2_SECRET_ACCESS_KEY'),
         'region' => 'us-east-1', // R2 doesn't use specific regions, but this is required
         'bucket' => env('CLOUDFLARE_R2_BUCKET'),
         'url' => env('CLOUDFLARE_R2_URL'),
         'visibility' => 'private',
         'endpoint' => env('CLOUDFLARE_R2_ENDPOINT'),
         'use_path_style_endpoint' => env('CLOUDFLARE_R2_USE_PATH_STYLE_ENDPOINT', false),
         'throw' => false,
    ],
],

3. Add Environment Variables

Add the following variables to your .env file:

1
2
3
4
5
CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_key
CLOUDFLARE_R2_BUCKET=your_bucket_name
CLOUDFLARE_R2_ENDPOINT=https://<account_id>.r2.cloudflarestorage.com
CLOUDFLARE_R2_URL=https://<custom_domain_or_bucket_url>

Don’t forget to update your .env.example file as well to help other developers set up their environments.

4. Using the R2 Storage in Your Laravel Application

Once configured, you can use the R2 storage disk like any other filesystem in Laravel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Storing files
Storage::disk('r2')->put('path/to/file.jpg', $fileContents);

// Store a file from a request
$path = $request->file('avatar')->store('avatars', 'r2');

// Generate a temporary URL for a private file
$url = Storage::disk('r2')->temporaryUrl(
    'path/to/file.jpg', now()->addMinutes(5)
);

// Check if a file exists
if (Storage::disk('r2')->exists('path/to/file.jpg')) {
    // File exists
}

// Delete a file
Storage::disk('r2')->delete('path/to/file.jpg');

5. Setting R2 as Your Default Disk (Optional)

If you want to use R2 as your default storage disk, update your .env file:

1
FILESYSTEM_DISK=r2

This allows you to use Storage methods without specifying the disk:

1
2
// Using the default disk (r2)
Storage::put('file.jpg', $contents);

6. Setting Up Public Access for Your R2 Bucket

To get the CLOUDFLARE_R2_URL value for your .env file, you need to set up public access to your Cloudflare R2 bucket. There are two main approaches:

Method 1: Use Cloudflare’s Default Public Access (R2.dev domain)

  1. Log in to your Cloudflare dashboard
  2. Go to ā€œR2ā€ from the sidebar
  3. Select your bucket
  4. Click on ā€œSettingsā€ tab
  5. Scroll down to ā€œPublic Accessā€
  6. Enable ā€œPublic Accessā€
  7. Once enabled, Cloudflare will provide you with a public URL in this format: https://pub-{hash}.r2.dev
  8. Copy this URL and add it to your .env file:
    1
    
    CLOUDFLARE_R2_URL=https://pub-{hash}.r2.dev
    

Method 2: Custom Domain with Cloudflare R2

If you want to use your own domain (like assets.example.com):

  1. Create a DNS record in your Cloudflare domain settings
  2. Set up a Custom Domain in the R2 bucket settings
  3. Configure the appropriate bucket policies
  4. Use your custom domain as the R2 URL:
    1
    
    CLOUDFLARE_R2_URL=https://assets.example.com
    

Additional Configuration

You might also need to:

  • Set up a bucket policy to control access
  • Ensure CORS settings are properly configured if accessing files from a browser
  • Consider creating a separate bucket just for public assets

Once you’ve set up public access and obtained the URL, update your .env file. Your file upload service will then use this URL to generate accessible links to your stored images.

Why Choose Cloudflare R2 Specifically?

šŸ’ø No Egress Fees

Unlike AWS S3 and most other cloud storage providers, Cloudflare R2 charges zero egress fees. This means you won’t pay extra when users download files from your application, making it ideal for media-heavy applications or those with high download volumes.

🌐 Integrated CDN

R2 integrates seamlessly with Cloudflare’s global CDN network, ensuring your files are delivered quickly to users worldwide.

šŸ”„ S3 Compatibility

The S3-compatible API means you can use existing S3 libraries and tools, making migration from AWS relatively straightforward.

šŸ’² Simple Pricing

R2’s pricing model is straightforward: $0.015/GB for storage and $4.50 per million class A operations (uploads), with no charges for downloads.

Implementation Example: File Upload Controller

Here’s a practical example of a controller method that handles file uploads to R2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class FileUploadController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
            'file' => 'required|file|max:10240', // 10MB max
        ]);
        
        // Upload file to R2
        $path = $request->file('file')->store('uploads', 'r2');
        
        // Generate a temporary URL valid for 1 hour
        $url = Storage::disk('r2')->temporaryUrl($path, now()->addHour());
        
        // Return the file path and temporary URL
        return response()->json([
            'success' => true,
            'path' => $path,
            'url' => $url,
            'message' => 'File uploaded successfully'
        ]);
    }
}

Testing Your Implementation

When testing file uploads to R2 with tools like Postman or API Dog:

šŸ“¤ Endpoint Details

  • Method: POST
  • URL: https://your-app.com/api/upload
  • Headers: Accept: application/json
  • Body: Form-data with key file and file value

Resources

For more detailed information on integrating Cloudflare R2 with Laravel, check out these excellent resources:

Conclusion

Implementing external storage buckets like Cloudflare R2 in your Laravel applications offers numerous benefits: improved scalability, better performance, enhanced security, and often cost savings. As applications grow and user expectations for speed and reliability increase, moving away from local file storage becomes less of a luxury and more of a necessity.

By following the implementation steps outlined above, you can quickly set up Cloudflare R2 with Laravel’s filesystem, giving your application a more robust and scalable approach to file storage.

Have you implemented external storage in your Laravel applications? What benefits have you observed? Share your experiences in the comments below!

This post is licensed under CC BY 4.0 by the author.