Integrating Cloudflare R2 with Laravel for File Storage
Laravel provides a robust filesystem abstraction through Flysystem, a PHP file storage library developed by Frank de Jonge. Flysystem offers a unified interface to interact with various filesystems, including Amazon Web Services (AWS) S3-compatible object storage solutions. Currently, the market features several S3 API-compatible object storage providers, such as Amazon S3, DigitalOcean Spaces, Linode Object Storage, and Cloudflare R2, among others.
When selecting an S3-compatible object storage service, several factors must be considered, including project requirements, available features, geographical location, and cost. For many users, including myself, cost is often the decisive factor. I consistently prefer Cloudflare R2 due to its affordability and the absence of egress fees.
This guide will demonstrate how to integrate Cloudflare R2 object storage into your Laravel project.
Prerequisites
Before proceeding, it is essential to have a fundamental understanding of Laravel's Storage system, including its purpose and functionality. To subscribe to Cloudflare R2, you will require a credit card or PayPal account. Cloudflare R2 offers a free tier, with pay-as-you-go pricing applicable once usage exceeds the free limits. You can estimate your costs using the R2 Cost Calculator.
Creating a Cloudflare Account
To create a bucket, you must subscribe to R2 through the Cloudflare dashboard. If you do not already have a Cloudflare account, follow these steps:
Sign Up for Cloudflare:
Visit the Cloudflare Sign-Up Page and create an account.
Upon registration, click the "Explore All Products" link to navigate to the Cloudflare dashboard.
Verify your email address to activate your account and gain access to Cloudflare services.
Email Verification:
- After signing up, you will be prompted to verify your email. Complete this step to proceed.
Creating a New R2 Bucket
Once your Cloudflare account is set up and verified, follow these steps to create a new R2 bucket:
Access R2:
- In the Cloudflare dashboard, select "R2" from the left sidebar.
Subscribe to R2:
Fill out the R2 subscription form with your billing details and preferred payment method (credit card or PayPal).
If you already have an existing bucket, you can skip the subscription process.
Create the Bucket:
After a successful subscription, you will be directed to the R2 dashboard.
Click on "Create a Bucket."
Configure Bucket Settings:
Enter a name for your bucket following your preferred naming conventions.
Adjust any additional settings as needed or retain the default options.
Click "Create Bucket" to finalize the creation process.
Bucket Confirmation:
- Upon successful creation, you will see an empty R2 bucket ready for use.
Generating R2 Credentials
To manage your R2 bucket contents within Laravel, you must generate credentials for the S3 client:
Manage API Tokens:
- In the Cloudflare dashboard, navigate to "R2" and select "Manage R2 API Tokens."
Create an API Token:
Click on "Create API Token."
Provide a descriptive name for your token.
Assign "Object Read & Write" permissions.
Restrict permissions to specific buckets, selecting the bucket you created earlier.
Retrieve Access Keys:
After creating the token, note down the Secret Access Key and Access Key ID.
Save these credentials as
R2_ACCESS_KEY_ID
andR2_SECRET_ACCESS_KEY
, respectively.Also, note the jurisdiction-specific endpoint URL for S3 clients as
R2_ENDPOINT
.It is crucial to record these values immediately, as the Secret Access Keys cannot be retrieved later.
Finalize:
- Once the keys are saved, click "Finish."
Configuring Laravel to Use R2
With your Cloudflare R2 credentials ready, proceed to configure your Laravel application:
Update Environment Variables:
Open the
.env
file in your Laravel project.Add the following entries with your specific credentials:
CLOUDFLARE_R2_ACCESS_KEY_ID=d7a57aecf9ff51c381sdfsdfsdf63f4db CLOUDFLARE_R2_SECRET_ACCESS_KEY=b8844faa70sdfsdfb0cfa92dfgdfdfgdfg CLOUDFLARE_R2_BUCKET=track360 CLOUDFLARE_R2_ENDPOINT=https://ksdfjsijd892374.r2.cloudflarestorage.com CLOUDFLARE_R2_URL=https://cdn.example.com CLOUDFLARE_R2_TOKEN=sjdfuwserskfjskdfuiesljrlksdf
Modify Filesystem Configuration:
Open
config/filesystems.php
.Add a new disk configuration for R2 as shown below:
<?php return [ 'default' => env('FILESYSTEM_DISK', 'local'), 'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], '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' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), ], 'r2' => [ 'driver' => 's3', 'key' => env('CLOUDFLARE_R2_ACCESS_KEY_ID'), 'secret' => env('CLOUDFLARE_R2_SECRET_ACCESS_KEY'), 'region' => 'auto', // Cloudflare R2 doesn't have specific regions, so 'us-east-1' is fine. '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, ], ], 'links' => [ public_path('storage') => storage_path('app/public'), ], ];
Install Flysystem S3 Package:
Use Composer to install the Flysystem S3 package required for integration:
composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies
Testing the Integration
To verify the successful integration of Cloudflare R2 with your Laravel application, perform the following test:
Upload a Sample File:
Use Laravel's Artisan Tinker to upload a file, such as
public/favicon.ico
:php artisan tinker
Within the Tinker shell, execute the following commands:
$file = public_path('favicon.ico'); Storage::disk('r2')->put('favicon.ico', file_get_contents($file));
A successful upload will return
true
.
Verify the Upload:
Still within the Tinker shell, list all files in the R2 bucket:
Storage::disk('r2')->allFiles();
The output should include
"favicon.ico"
.[ "favicon.ico", ]
Confirm in Cloudflare Dashboard:
- Navigate to the R2 bucket dashboard in Cloudflare to ensure that
favicon.ico
appears in the bucket.
- Navigate to the R2 bucket dashboard in Cloudflare to ensure that
If the file is present, the integration has been successfully completed.
Conclusion
Integrating Cloudflare R2 with Laravel offers a cost-effective and efficient solution for object storage. By following this guide, you can set up a Cloudflare R2 bucket, generate the necessary credentials, and configure your Laravel application to utilize R2 for file storage. Cloudflare R2's free tier, pay-as-you-go pricing, and zero egress fees make it an excellent choice for optimizing both costs and performance. We hope this guide has been informative and helpful. Please feel free to leave comments or questions in the discussion section.