Production-ready async library for multi-tenant SaaS platforms with Cloudflare R2 and Workers
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloudflare_saas-1.0.4.tar.gz.
File metadata
- Download URL: cloudflare_saas-1.0.4.tar.gz
- Upload date:
- Size: 25.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
110066093a861324a3b490a9bdbad02bceab46f158656870879f395f866f580e
|
|
| MD5 |
03a7ceeedc838e6fbb2e26334a007c76
|
|
| BLAKE2b-256 |
45701aae2daf5f8605d856883fa8842a0824ae0dce9b0d3713c3b7837f085ec9
|
File details
Details for the file cloudflare_saas-1.0.4-py3-none-any.whl.
File metadata
- Download URL: cloudflare_saas-1.0.4-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af757d058fa9407d5202a725ff8fc1bfd7bafecbc99e02b7b20778149fbbb967
|
|
| MD5 |
96efcb0d6bffd970a018db6a38c5b1cd
|
|
| BLAKE2b-256 |
3a869acb1a8bfa0a91a4c80b34dc77efd041e3907891a0f27f45c039a6068132
|