Nandung R2 - Cloudflare R2 Storage
Seamlessly integrate your WordPress Media Library with Cloudflare R2 storage. Automatically upload, serve, and manage media files through R2's powerful and cost-effective object storage.
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/nandunkz/nandung-r2/archive/refs/heads/main.zipNandung R2 - WordPress Media Library with Cloudflare R2
for Developers, see README-DEV.md
Seamlessly integrate your WordPress Media Library with Cloudflare R2 storage. Automatically upload, serve, and manage media files through R2's powerful and cost-effective object storage.
🌟 Features
Core Features
- 🚀 Automatic Upload - Media files automatically uploaded to R2 when added to Media Library
- 🔄 URL Replacement - Serve media files directly from R2 CDN with automatic URL replacement
- ⚡ Fast Migration - Bulk migrate existing media files between local storage and R2
- 🎯 Bidirectional Sync - Transfer files from local to R2 or R2 back to local
- 🔒 Secure - Built with WordPress security best practices
- 🌍 Multilingual - Full support for English and Indonesian languages
Advanced Options
- Auto-delete local files - Save disk space by removing local files after R2 upload
- Srcset rewrite - Optimize responsive images with R2 URLs for all sizes
- Role-based access - Control who can delete media files
- Real-time testing - Test R2 connection before going live
Developer Friendly
- Clean, well-documented code
- Composer autoloading support
- PSR-4 namespacing
- Comprehensive error handling
- Extensible architecture
📋 Requirements
- WordPress: 5.0 or higher
- PHP: 7.4 or higher
- Cloudflare R2: Active account with configured bucket
PHP Extensions
curl- For R2 API communicationjson- For data handlingmbstring- For string operations
🚀 Installation
Method 1: Manual Installation
- Download the plugin files
- Extract to
wp-content/plugins/nandung-r2/ - Activate the plugin in WordPress Admin → Plugins
- Configure your R2 credentials in Settings
Method 2: WordPress Upload
- Go to Plugins → Add New
- Click Upload Plugin
- Choose the plugin ZIP file
- Click Install Now
- Activate the plugin
⚙️ Configuration
Step 1: Get Cloudflare R2 Credentials
1. Create R2 Bucket
- Log in to Cloudflare Dashboard
- Go to R2 section
- Click Create Bucket
- Enter bucket name (e.g.,
my-media-bucket) - Choose location (optional)
- Click Create Bucket
2. Get Account ID
- In R2 dashboard
- Copy your Account ID (displayed at top)
3. Create API Token
- Click Manage R2 API Tokens
- Click Create API Token
- Select Read & Write permissions
- Click Create API Token
- Copy Access Key ID and Secret Access Key
- ⚠️ Save secret key immediately - it won't be shown again!
4. Get Public URL
- Go to your bucket settings
- Click Settings tab
- Under Public Access, click Connect Domain
- Add your custom domain or use R2.dev URL
- Copy the public URL (e.g.,
https://media.yourdomain.com)
Step 2: Configure Plugin
- Go to Nandung R2 → Settings
- Fill in your credentials:
- Account ID: Your Cloudflare Account ID
- Access Key ID: R2 API Access Key ID
- Secret Access Key: R2 API Secret Access Key
- Bucket Name: Your R2 bucket name
- Public URL: Your R2 public access URL
- Click Save Settings
- Click Test Connection to verify
Step 3: Configure Advanced Options (Optional)
- Go to Nandung R2 → Advanced
- Configure options:
- Delete local files after upload: Save disk space (⚠️ use with caution)
- Enable srcset rewrite: Optimize responsive images
- Click Save Advanced Options
📖 Usage Guide
Uploading New Media
Automatic Upload (Recommended)
- Go to Media → Add New
- Upload your files normally
- Files are automatically uploaded to R2
- URLs are automatically replaced with R2 URLs
What Happens?
1. You upload image.jpg to WordPress
2. Plugin uploads to R2: bucket/2025/01/image.jpg
3. WordPress uses R2 URL: https://media.yourdomain.com/2025/01/image.jpg
4. Local file is kept (unless auto-delete is enabled)
Migrating Existing Media
Migrate All Media to R2
- Go to Nandung R2 → Tools
- In Migrate Media Files section
- Set Batch Size (default: 10)
- Click Migrate Local → R2
- Wait for migration to complete
- Check the log for details
Migrate from R2 to Local
- Go to Nandung R2 → Tools
- Click Migrate R2 → Local
- Files are downloaded from R2 to local storage
- Useful for backup or reverting
Testing Connection
Quick Test from Settings
- Go to Nandung R2 → Settings
- Scroll to Quick Actions
- Click Test Connection
- View detailed log output
Advanced Testing
- Go to Nandung R2 → Tools
- Click Test R2 Connection
- View comprehensive connection details:
- Account ID verification
- Bucket access check
- Response time
- Connection status
Scanning for Missing Files
If some files are missing R2 metadata:
- Go to Nandung R2 → Tools
- Click Scan Missing R2 Meta
- Plugin identifies files without R2 data
- Optionally re-upload missing files
🎛️ Advanced Features
Auto-Delete Local Files
⚠️ Important: Use with caution in production!
When to enable:
- You need to save disk space
- Your R2 connection is stable and reliable
- You have backups elsewhere
- You don't need local file access
How to enable:
- Go to Nandung R2 → Advanced
- Check Delete local file after upload
- Click Save Advanced Options
What happens:
- After successful R2 upload, local file is deleted
- Only R2 URL remains in database
- Cannot be reversed automatically
Srcset Rewrite for Responsive Images
What is srcset?
WordPress generates multiple image sizes (thumbnail, medium, large) and uses srcset attribute for responsive images.
When to enable:
- All image sizes are uploaded to R2
- You want full CDN performance
- Your theme uses responsive images
How to enable:
- Go to Nandung R2 → Advanced
- Check Enable srcset rewrite
- Click Save Advanced Options
Example:
<!-- Before -->
<img srcset="
/wp-content/uploads/2025/01/image-300x200.jpg 300w,
/wp-content/uploads/2025/01/image-768x512.jpg 768w,
/wp-content/uploads/2025/01/image-1024x683.jpg 1024w
">
<!-- After -->
<img srcset="
https://media.yourdomain.com/2025/01/image-300x200.jpg 300w,
https://media.yourdomain.com/2025/01/image-768x512.jpg 768w,
https://media.yourdomain.com/2025/01/image-1024x683.jpg 1024w
">
Batch Size Configuration
Control migration speed and server load:
- Small (5-10): Safer for large files or slow connections
- Medium (10-25): Balanced performance
- Large (25-50): Faster but more resource intensive
Recommendation:
- Start with default (10)
- Increase gradually if no issues
- Monitor server performance
🔧 Troubleshooting
Connection Failed
Symptoms:
- "Connection failed" message
- Unable to upload to R2
- Test connection fails
Solutions:
- Check credentials - Verify Account ID, Access Key, Secret Key
- Check bucket name - Must match exactly (case-sensitive)
- Check API token permissions - Must have Read & Write access
- Check public URL - Must be valid and accessible
- Check firewall - Ensure WordPress can make outbound HTTPS requests
Files Not Uploading
Symptoms:
- Files upload to WordPress but not R2
- No R2 URL in database
- Missing metadata
Solutions:
- Test connection - Use Tools → Test R2 Connection
- Check PHP memory - Large files need more memory
- Check file permissions - WordPress must be able to read files
- Check error logs - Look in
wp-content/debug.log
URLs Not Rewriting
Symptoms:
- Files on R2 but still showing local URLs
- Old URLs in content
Solutions:
- Check R2 metadata - Use Tools → Scan Missing R2 Meta
- Regenerate metadata - Re-upload files if needed
- Clear cache - If using caching plugin
- Check public URL - Must be correctly configured
Migration Stuck
Symptoms:
- Migration stops mid-process
- Progress bar doesn't move
- Timeout errors
Solutions:
- Reduce batch size - Try smaller chunks (5-10)
- Check server resources - CPU, memory, disk space
- Increase PHP limits -
max_execution_time,memory_limit - Check network - Ensure stable connection to Cloudflare
Performance Issues
Symptoms:
- Slow upload speed
- Timeouts during migration
- High server load
Solutions:
- Reduce batch size - Process fewer files at once
- Optimize images - Compress before upload
- Upgrade hosting - Consider more powerful server
- Use off-peak hours - Migrate during low traffic
📊 Statistics & Monitoring
Dashboard Overview
Go to Nandung R2 → Tools to view:
- Total Attachments: All media files in library
- On R2: Files successfully uploaded to R2
- Missing R2 Meta: Files without R2 metadata
Migration Log
Real-time log shows:
- Files processed
- Success count
- Skipped count
- Error messages
- Processing time
Connection Log
Detailed connection test output:
- Account ID verification
- Bucket name confirmation
- Response time measurement
- Connection status
- Error details (if any)
🌍 Multi-Language Support
Available Languages
- English (en_US) - Default
- Bahasa Indonesia (id_ID) - Complete translation
Change Language
- Go to Settings → General
- Select Site Language
- Choose your preferred language
- Save changes
- Reload plugin pages
Add New Language
See languages/README.md for translation guide.
🔐 Security
Data Protection
- API credentials encrypted at rest
- Nonce verification on all AJAX requests
- Capability checks for all actions
- Input sanitization and validation
- Output escaping for all display
Best Practices
- Use strong API tokens - Generate unique tokens
- Limit permissions - Only grant necessary access
- Regular backups - Backup before major changes
- Monitor logs - Check for suspicious activity
- Keep updated - Install plugin updates promptly
🆘 Support & Resources
Documentation
- Plugin Settings: Nandung R2 → Settings → About
- Translation Guide:
languages/README.md - Developer Guide:
README-DEV.md
Getting Help
Before Asking for Help:
- Check this README
- Test your R2 connection
- Check WordPress debug log
- Try with default WordPress theme
- Disable other plugins temporarily
Where to Get Help:
- GitHub Issues: https://github.com/nandung/nandung-r2/issues
- WordPress Forum: https://wordpress.org/support/plugin/nandung-r2
- Email Support: contact@nandung.id
When Reporting Issues, Include:
- WordPress version
- PHP version
- Plugin version
- Error messages (from debug log)
- Steps to reproduce
- Screenshots (if relevant)
🎯 Performance Tips
Optimization Strategies
-
Use CDN custom domain
- Better branding
- Improved caching
- Faster DNS resolution
-
Enable srcset rewrite
- Responsive images from R2
- Better mobile performance
- Reduced bandwidth
-
Optimize images before upload
- Compress images
- Convert to WebP
- Resize appropriately
-
Use auto-delete wisely
- Save server disk space
- Reduce backup size
- Ensure R2 reliability first
-
Migrate in batches
- Don't overload server
- Monitor during migration
- Use off-peak hours
📝 Changelog
Version 1.0.0 (2025-01-05)
- 🎉 Initial release
- ✅ Automatic R2 upload on media library add
- ✅ URL replacement for R2-hosted files
- ✅ Bidirectional migration (Local ↔ R2)
- ✅ Connection testing with detailed logs
- ✅ Advanced options (auto-delete, srcset rewrite)
- ✅ Multi-language support (English, Indonesian)
- ✅ Role-based access control
- ✅ Comprehensive error handling
📜 License
This plugin is licensed under the GPL v2 or later.
Copyright (C) 2025 Nandung
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
🙏 Credits
Built With
- AWS SDK for PHP - S3-compatible API client
- TailwindCSS - UI styling
- WordPress core functions and APIs
Contributors
- Nandung Team - Initial development
Special Thanks
- Cloudflare for R2 storage platform
- WordPress community for excellent documentation
🔗 Links
- Plugin Homepage: https://nandung.id/nandung-r2
- GitHub Repository: https://github.com/nandung/nandung-r2
- Cloudflare R2: https://www.cloudflare.com/products/r2/
- Support Forum: https://wordpress.org/support/plugin/nandung-r2
Made with ❤️ by Nandung
For developer documentation, see README-DEV.md