R2 S3 Signature V4 client in [src/R2/R2Client.php](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/src/R2/R2Client.php) SQLite mirror, usage ledger, settings, local tags, permission labels, and signed URL history under [src/Repository](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/src/Repository) Simple password auth and CSRF protection Uploads, folders, sync, copy/move/delete, downloads, presigned URLs, CORS JSON management, and usage/billing-style summaries Setup docs in [README.md](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/README.md) and config template in [.env.example](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/.env.example) Important R2 caveat: Cloudflare’s current R2 S3 compatibility docs say ACLs and object-tagging APIs are not implemented, so the app stores tags and permission labels locally in SQLite while keeping file bytes on R2. I used Cloudflare’s official docs for S3 compatibility, presigned URLs, and CORS.
CloudflareR2-Manager
A self-contained PHP web application for managing a Cloudflare R2 bucket with a local SQLite mirror.
Features
- Simple password authentication with CSRF protection.
- R2 object browser backed by SQLite, so normal navigation uses the local mirror instead of repeatedly listing the bucket.
- Prefix/folder organization, including zero-byte marker objects for empty folders.
- Upload one or more files directly to R2 with local tags, permission labels, and operator notes.
- Download, delete, copy, move, rename, and refresh object metadata.
- Generate presigned
GET,PUT,HEAD, andDELETEURLs. - Manage bucket CORS from JSON.
- Track local usage events for sync, upload, download, copy, move, delete, CORS, and signed URL generation.
- Optional public URL display for public buckets or custom R2 domains.
Cloudflare R2 Notes
Cloudflare R2 uses the S3-compatible API at https://<ACCOUNT_ID>.r2.cloudflarestorage.com and the S3 region is auto.
As of Cloudflare's R2 S3 compatibility docs updated June 8, 2026, S3 ACLs and object tagging APIs are not implemented by R2. This app therefore stores tags, permission labels, and notes locally in SQLite while keeping file bytes in R2. Bucket CORS, object list/get/put/delete/copy, and presigned URLs are handled through R2's S3-compatible API.
Requirements
- PHP 8.1 or newer.
- PHP extensions:
pdo_sqlite,curl,simplexml,fileinfo. - A Cloudflare R2 bucket.
- R2 API credentials with access to that bucket.
Composer is not required.
Setup
-
Copy the environment example:
cp .env.example .env -
Edit
.env:APP_PASSWORD="choose-a-real-password" R2_ACCOUNT_ID="your-cloudflare-account-id" R2_ACCESS_KEY_ID="your-r2-access-key-id" R2_SECRET_ACCESS_KEY="your-r2-secret-access-key" R2_BUCKET="your-bucket-name" -
Start the PHP development server:
php -S 127.0.0.1:8080 -t public -
Open
http://127.0.0.1:8080, sign in, and run Sync current prefix.
Password Hashes
For a plain setup, use APP_PASSWORD. For a hashed password, generate a hash with PHP and set APP_PASSWORD_HASH instead:
php -r 'echo password_hash("your-password", PASSWORD_DEFAULT), PHP_EOL;'
Public URLs
If your bucket has public access or a custom domain, set:
R2_PUBLIC_URL="https://static.example.com"
The app will display copyable public links. It does not make a bucket public; public access is controlled in Cloudflare.
Usage Tracking
The usage dashboard is a local operational ledger. It records actions performed through this app and current mirrored storage size. It is useful for estimating activity, but it is not a replacement for Cloudflare's official billing or analytics.
CORS Format
Enter CORS as an array of S3-style rules:
[
{
"AllowedOrigins": ["https://example.com"],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["Content-Type"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
Security
- Keep
.envoutside version control. - Serve the app behind HTTPS in production.
- Use least-privilege R2 credentials.
- Restrict access at your web server or VPN if this manages production buckets.