# 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. - Resumable browser uploads using R2 multipart upload URLs, suitable for large files and mobile Safari. - Optional side upload page with its own password and fixed destination prefix for quick iPhone uploads. - Download, delete, copy, move, rename, and refresh object metadata. - Generate presigned `GET`, `PUT`, `HEAD`, and `DELETE` URLs. - 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://.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 1. Copy the environment example: ```sh cp .env.example .env ``` 2. Edit `.env`: ```dotenv 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" ``` 3. Start the PHP development server: ```sh php -S 127.0.0.1:8080 -t public ``` 4. Open `http://127.0.0.1:8080`, sign in, and run **Sync current prefix**. ## Resumable Uploads The dashboard upload form uses browser-side R2 multipart uploads when JavaScript is available. PHP creates the multipart upload, signs each part URL, records completed part ETags in `storage/cache/uploads`, and completes the upload when all parts are present. If a connection drops, choose the same file again and the app will reuse the saved multipart session. Useful settings: ```dotenv UPLOAD_PART_SIZE=8388608 UPLOAD_PART_URL_TTL=3600 UPLOAD_SESSION_TTL=604800 R2_REQUEST_TIMEOUT=300 ``` `UPLOAD_PART_SIZE` is bytes. Keep it at or above `5242880` because S3-compatible multipart uploads require 5 MiB minimum parts except for the last part. Because file chunks upload from the browser directly to R2, your bucket CORS policy must allow the app origin to `PUT` and expose `ETag`. The default CORS editor example already includes `PUT` and `ETag`; change `AllowedOrigins` to your deployed app origin. ## Side Upload Page `/side-upload.php` is a narrow upload-only page for quick mobile uploads. It uses a separate password from the main app and always uploads into a configured prefix. Configure it in `.env`: ```dotenv SIDE_UPLOAD_PASSWORD="choose-a-different-password" SIDE_UPLOAD_PREFIX="iphone-uploads/" SIDE_UPLOAD_TAGS="source=iphone" ``` You can also edit the constants at the top of `public/side-upload.php`. Or copy `side-upload.example.json` to `side-upload.json` and edit the password and prefix there. The real `side-upload.json` file is ignored by git. ## Password Hashes For a plain setup, use `APP_PASSWORD`. For a hashed password, generate a hash with PHP and set `APP_PASSWORD_HASH` instead: ```sh php -r 'echo password_hash("your-password", PASSWORD_DEFAULT), PHP_EOL;' ``` ## Public URLs If your bucket has public access or a custom domain, set: ```dotenv 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: ```json [ { "AllowedOrigins": ["https://example.com"], "AllowedMethods": ["GET", "PUT", "HEAD"], "AllowedHeaders": ["Content-Type"], "ExposeHeaders": ["ETag"], "MaxAgeSeconds": 3600 } ] ``` ## Security - Keep `.env` outside 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.