Cloudflare R2 SaaS Platform Library
A production-ready Python async library for building multi-tenant SaaS platforms with Cloudflare R2, Workers, and Custom Hostnames.
Features
- ✅ Async R2 bucket operations (upload, delete, list)
- ✅ Tenant management with namespace isolation
- ✅ Custom domain onboarding with DNS verification
- ✅ Cloudflare for SaaS custom hostname provisioning
- ✅ Worker deployment automation via Terraform
- ✅ Configurable logging system (DEBUG, INFO, WARNING, ERROR, CRITICAL)
- ✅ Multiple log formats (simple, detailed, JSON)
- ✅ Full error handling and retry logic
- ✅ Type-safe with Pydantic models
- ✅ Comprehensive documentation
Installation
pip install cloudflare aiodns aioboto3 pydantic python-terraform httpx tenacity
For PostgreSQL storage:
pip install asyncpg
For development:
pip install -e ".[dev,web]"
Scripts
Working deployment and management scripts are available in the scripts/ folder:
deploy_worker.py- Deploy Cloudflare Worker script via APIcreate_token_with_global_key.py- Create API tokens with proper permissionscreate_r2_bucket.py- Create and manage R2 bucketstest_token_permissions.py- Test API token permissions (8 tests)
See scripts/README.md for detailed usage instructions.
Documentation
Comprehensive documentation is available in the docs/ folder:
- Complete System Guide - Full system overview and operational guide
- DNS Setup Guide - Domain configuration for getai.page
- Deployment Success - Deployment results and metrics
- Permissions Guide - API token permissions and setup
See docs/README.md for a complete list of documentation files.
Quick Start
Basic Usage with Logging
import asyncio
from cloudflare_saas import (
CloudflareSaaSPlatform,
Config,
configure_logging,
LogLevel
)
async def main():
# Configure logging
configure_logging(level=LogLevel.INFO)
# Load config from environment
config = Config.from_env()
# Initialize platform
platform = CloudflareSaaSPlatform(config)
# Create tenant
tenant = await platform.create_tenant("Acme Inc", "acme-123")
# Deploy site
await platform.deploy_tenant_site(
tenant.tenant_id,
local_path="./acme-site"
)
# Add custom domain
domain_status = await platform.add_custom_domain(
tenant.tenant_id,
"www.acme.com"
)
asyncio.run(main())
Configuration
Environment Variables
Required:
CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_IDCLOUDFLARE_ZONE_IDR2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_BUCKET_NAMEPLATFORM_DOMAIN
Optional - Logging:
LOG_LEVEL(default: INFO) - DEBUG, INFO, WARNING, ERROR, CRITICALLOG_FORMAT(default: detailed) - simple, detailed, jsonLOG_FILE- Path to log file (optional)ENABLE_CONSOLE_LOGGING(default: true) - Enable console output
Programmatic Configuration
from cloudflare_saas import Config
config = Config(
cloudflare_api_token="your-token",
cloudflare_account_id="your-account",
cloudflare_zone_id="your-zone",
r2_access_key_id="your-r2-key",
r2_secret_access_key="your-r2-secret",
r2_bucket_name="yourplatform-sites",
platform_domain="yourplatform.com",
log_level="DEBUG",
log_format="json",
log_file="app.log"
)
Logging
Configure Logging
from cloudflare_saas import configure_logging, LogLevel, LogFormat
# Simple console logging
configure_logging(level=LogLevel.INFO)
# Detailed file logging
configure_logging(
level=LogLevel.DEBUG,
log_format=LogFormat.DETAILED,
log_file="cloudflare-saas.log"
)
# JSON logging for production
configure_logging(
level=LogLevel.WARNING,
log_format=LogFormat.JSON,
log_file="/var/log/cloudflare-saas.log",
enable_console=False
)
Log Levels
- DEBUG: Detailed diagnostic information
- INFO: General informational messages
- WARNING: Warning messages
- ERROR: Error messages
- CRITICAL: Critical errors
Log Formats
- simple: Minimal output
INFO: message - detailed: With timestamps and source
2025-12-17 10:30:45 - Module - INFO - [file.py:65] - message - json: Structured JSON for log aggregation
Using Loggers in Your Code
from cloudflare_saas import get_logger, LoggerMixin
# Get a logger
logger = get_logger(__name__)
logger.info("Starting operation")
# Use in a class
class MyService(LoggerMixin):
def do_work(self):
self.logger.info("Working...")
Documentation
Comprehensive documentation is available at Read the Docs.
Build Documentation Locally
# Install documentation dependencies
make install-docs
# Build HTML documentation
make docs
# Serve documentation locally
make docs-serve
Documentation includes:
- Getting Started Guide: Quick start and installation
- Configuration Guide: All configuration options
- Logging Guide: Comprehensive logging documentation
- API Reference: Complete API documentation
- Examples: Practical code examples
- Deployment Guide: Production deployment
- Contributing Guide: Development guidelines
Development
Available Make Commands
make help # Show all available commands
# Development
make install # Install package
make install-dev # Install with dev dependencies
make install-docs # Install documentation dependencies
# Testing
make test # Run tests
make test-cov # Run tests with coverage
make test-watch # Run tests in watch mode
# Code Quality
make lint # Run linters (ruff, mypy)
make format # Format code (black, ruff)
make check # Run all checks (lint + test)
# Documentation
make docs # Build documentation
make docs-serve # Build and serve documentation
make docs-clean # Clean documentation build
# Docker
make docker-build # Build Docker image
make docker-run # Run Docker container
make docker-stop # Stop Docker containers
# API
make run-api # Run FastAPI development server
# Utilities
make clean # Clean build artifacts
make clean-all # Clean all generated files
Running Tests
# Run all tests
make test
# Run with coverage
make test-cov
# Run specific test
pytest tests/test_platform.py::test_create_tenant -v
Code Quality
# Format code
make format
# Check linting
make lint
# Run all checks
make check
Architecture
See cloudflare_r2_plan.md for detailed architecture.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Development Setup
- Fork and clone the repository
- Install development dependencies:
make install-dev - Create a branch for your feature
- Make your changes with tests
- Run tests and linting:
make check - Submit a pull request
License
[Add your license here]
Support
- Documentation: https://cloudflare-saas.readthedocs.io/
- Issues: https://github.com/yourusername/cloudflare-saas/issues
- Discussions: https://github.com/yourusername/cloudflare-saas/discussions
Metadata
Release files for cloudflare-saas 1.0.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cloudflare_saas-1.0.8.tar.gz | 25.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cloudflare_saas-1.0.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.2 kB
Release files / cloudflare_saas-1.0.8.tar.gz
| Download URL | cloudflare_saas-1.0.8.tar.gz |
|---|---|
| Size | 25.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
39f22e0cc7d601bd07c25ee6a3bd5b901d769fd2b1fcc56484cfe8d188019003
|
|
BLAKE2b-256 checksum How to use checksums |
5155c9927fd149f907ffbfffb2bff285506ed7f068a73f2756a2f8b63ac0e200
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|
Release files / cloudflare_saas-1.0.8-py3-none-any.whl
| Download URL | cloudflare_saas-1.0.8-py3-none-any.whl |
|---|---|
| Size | 26.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
62115e33c18417bea1e36ffecf0ff3731a1998e95b4a1367b99932025ec74cf1
|
|
BLAKE2b-256 checksum How to use checksums |
fdec9f364477f3ad59f1a01d7d31445806199d793f59519f4bc0261efa11b233
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|