# Configuration Reference Complete configuration examples for different S3-compatible storage providers. > Examples use placeholder values. Replace with your own keys, bucket names, and endpoints. ## Table of contents - [Conventions](#conventions) - [Cloudflare R2](#cloudflare-r2) - [Getting R2 credentials](#getting-r2-credentials) - [Custom domain (optional)](#custom-domain-optional) - [AWS S3](#aws-s3) - [S3 permissions required](#s3-permissions-required) - [MinIO (Self-hosted)](#minio-self-hosted) - [MinIO setup](#minio-setup) - [Backblaze B2](#backblaze-b2) - [B2 S3-compatible keys](#b2-s3-compatible-keys) - [Wasabi](#wasabi) - [Multiple buckets](#multiple-buckets) - [Local mode](#local-mode) - [Security best practices](#security-best-practices) ## Conventions - `endpoint` should be the provider API base URL **without** bucket path. - If `public_url` is omitted, it defaults to `endpoint/` (path-style). - For custom domains mapped to a bucket, set `public_url` to the domain root (no bucket segment). - Optional `session_token` is supported for temporary credentials. ## Cloudflare R2 ```yaml default: my-r2-bucket buckets: my-r2-bucket: endpoint: https://.r2.cloudflarestorage.com access_key_id: your_access_key_id secret_access_key: your_secret_access_key bucket_name: my-bucket public_url: https://cdn.example.com # Optional: custom domain # session_token: optional for temporary credentials region: auto ``` ### Getting R2 credentials 1. Go to Cloudflare Dashboard → R2 2. Create a bucket (or use existing one) 3. Go to R2 API Tokens: `https://dash.cloudflare.com//r2/api-tokens` 4. Create API Token: - **Permissions**: Object Read & Write - **Bucket**: Select your specific bucket (recommended for security) 5. Copy Access Key ID and Secret Access Key 6. Your Account ID is in the URL: `dash.cloudflare.com//` ### Custom domain (optional) 1. In R2 bucket settings, go to "Custom Domains" 2. Add your domain (e.g., `cdn.example.com`) 3. Add CNAME record pointing to your R2 bucket 4. Wait for SSL certificate provisioning 5. Use the custom domain as `public_url` ## AWS S3 ```yaml default: aws-production buckets: aws-production: endpoint: https://s3.us-east-1.amazonaws.com access_key_id: AKIAIOSFODNN7EXAMPLE secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY # session_token: optional for temporary credentials bucket_name: my-company-assets public_url: https://my-company-assets.s3.amazonaws.com region: us-east-1 aws-backup: endpoint: https://s3.eu-west-1.amazonaws.com access_key_id: AKIAIOSFODNN7EXAMPLE secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY bucket_name: my-company-backups region: eu-west-1 ``` ### S3 permissions required Your IAM user needs these permissions: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-bucket/*" } ] } ``` ## MinIO (Self-hosted) ```yaml default: minio-local buckets: minio-local: endpoint: http://localhost:9000 access_key_id: minioadmin secret_access_key: minioadmin bucket_name: my-bucket public_url: http://localhost:9000/my-bucket region: us-east-1 minio-production: endpoint: https://minio.company.internal:9000 access_key_id: service-account secret_access_key: super-secret-key bucket_name: production-assets public_url: https://assets.company.internal region: us-east-1 ``` ### MinIO setup ```bash # Start MinIO locally docker run -p 9000:9000 -p 9001:9001 \ -e "MINIO_ROOT_USER=minioadmin" \ -e "MINIO_ROOT_PASSWORD=minioadmin" \ minio/minio server /data --console-address ":9001" # Create bucket mc alias set local http://localhost:9000 minioadmin minioadmin mc mb local/my-bucket ``` ## Backblaze B2 ```yaml default: b2-assets buckets: b2-assets: endpoint: https://s3.us-west-002.backblazeb2.com access_key_id: your_key_id secret_access_key: your_application_key bucket_name: my-b2-bucket public_url: https://f002.backblazeb2.com/file/my-b2-bucket region: us-west-002 ``` ### B2 S3-compatible keys 1. In B2 console, go to "Application Keys" 2. Create new key with: - **Type**: Application Key - **Allow access to**: Single bucket or all buckets - **Permissions**: Read and Write 3. The "keyID" is your `access_key_id` 4. The "applicationKey" is your `secret_access_key` ## Wasabi ```yaml default: wasabi-primary buckets: wasabi-primary: endpoint: https://s3.us-east-1.wasabisys.com access_key_id: your-access-key secret_access_key: your-secret-key bucket_name: my-wasabi-bucket public_url: https://s3.us-east-1.wasabisys.com/my-wasabi-bucket region: us-east-1 ``` ## Multiple buckets You can define multiple buckets and switch between them: ```yaml default: production buckets: production: endpoint: https://xxx.r2.cloudflarestorage.com access_key_id: prod-key secret_access_key: prod-secret bucket_name: prod-assets public_url: https://cdn.example.com region: auto staging: endpoint: https://yyy.r2.cloudflarestorage.com access_key_id: staging-key secret_access_key: staging-secret bucket_name: staging-assets public_url: https://staging-cdn.example.com region: auto backups: endpoint: https://s3.us-east-1.amazonaws.com access_key_id: AKIA... secret_access_key: ... bucket_name: company-backups region: us-east-1 ``` Switch buckets with `--bucket`: ```bash # Use default (production) python3 scripts/r2-upload.py file.jpg --public # Use staging bucket python3 scripts/r2-upload.py file.jpg --bucket staging --public # Use backups bucket python3 scripts/r2-upload.py backup.zip --bucket backups --key "backups/YYYY/MM/DD/backup.zip" ``` ## Local mode Local mode copies files to a local `public` directory instead of uploading to remote storage. Useful for development and testing. ```yaml default: local-dev buckets: local-dev: mode: local endpoint: http://localhost:8001/public # Base URL for accessing files public_dir: public # Target directory (relative to cwd or absolute) ``` ### Configuration fields | Field | Required | Description | |---|---|---| | `mode` | Yes | Must be `local` | | `endpoint` | Yes | Base URL used to build the returned file URL | | `public_dir` | No | Directory to copy files into (default: `public`) | ### How it works 1. File is copied to `/` (directories are created automatically) 2. Returns `/` as the URL ### Example ```bash # Upload to local public directory python3 scripts/r2-upload.py ./photo.jpg --bucket local-dev # With custom key python3 scripts/r2-upload.py ./photo.jpg --bucket local-dev --key images/photo.jpg # File copied to: public/images/photo.jpg # Returns: http://localhost:8001/public/images/photo.jpg ``` ## Security best practices 1. **File permissions**: Set config file to 600 ```bash chmod 600 scripts/.r2-upload.yml ``` 2. **Separate credentials**: Use different keys for different environments 3. **Least privilege**: Grant only `PutObject`, `GetObject`, `DeleteObject` permissions 4. **Rotate keys**: Regularly rotate access keys, especially for production