Backblaze B2 Integration
Backblaze B2 is an S3-compatible object storage service with zero egress fees and low-cost storage. Sveltia CMS supports B2 as a media storage backend with direct browser-to-B2 uploads using AWS Signature Version 4 — no backend proxy is required.
Requirements
- A Backblaze account with a B2 bucket created.
- A B2 Application Key (see Credentials below).
- CORS configuration via CLI (see CORS below) — the web console doesn’t support the required S3 operations.
CSP
If your site uses a Content Security Policy (CSP), you need to allow the B2 endpoint. See Content Security Policy below for details.
Setup
Credentials
B2 uses Application Keys for authentication. You can create keys via Backblaze Console > Account > Application Keys.
For production use, create a bucket-scoped Application Key with the following capabilities:
listFilesreadFileswriteFilesdeleteFiles
Using the B2 CLI:
b2 key create --bucket my-bucket sveltia-cms listFiles,readFiles,writeFiles,deleteFilesThe resulting keyID goes in access_key_id in your config. The applicationKey (shown only once) is entered by users in the CMS UI when they access the media library for the first time — it is never stored in config.
Public Read Access
For asset previews and downloads to work, objects must be publicly readable. When creating a bucket, set its visibility to Public:
b2 bucket create my-bucket allPublicINFO
Making a bucket public requires a payment method on your Backblaze account. Alternatively, you can use a private bucket with a custom public_url pointing to a CDN that provides public access.
With a public bucket, B2’s S3 endpoint serves objects anonymously, so no separate public_url configuration is needed — asset URLs use the virtual-hosted storage endpoint directly (https://{bucket}.s3.{region}.backblazeb2.com/{key}).
CORS
Important
The CORS configuration required by Sveltia CMS cannot be set via the B2 web console. The console only offers four basic presets that don’t include the S3 operations needed for uploads and listings. You must use the B2 CLI, native API, or AWS CLI to configure CORS.
This is documented, by-design behavior — see Enable and Manage CORS Rules in the Enterprise Web Console.
CORS is required because Sveltia CMS sends custom AWS Signature v4 headers that trigger a preflight request.
Setting CORS via B2 CLI
1. Install and authorize the B2 CLI (use a key with writeBuckets capability):
See the official documentation for installation instructions.
b2 account authorize <adminKeyId> <adminKey>2. Set the CORS rule with S3 operations:
b2 bucket update --cors-rules '[{
"corsRuleName": "sveltia-cms",
"allowedOrigins": ["https://your-cms-domain.com"],
"allowedOperations": ["s3_get", "s3_head", "s3_put", "s3_delete", "s3_post"],
"allowedHeaders": ["*"],
"exposeHeaders": ["ETag", "x-amz-request-id"],
"maxAgeSeconds": 3600
}]' my-bucket allPublicReplace https://your-cms-domain.com with your actual CMS origin and my-bucket with your bucket name. A wildcard * is allowed for allowedOrigins if you want to allow all origins.
TIP
You can also pass --cors-rules to b2 bucket create to set CORS when creating the bucket.
See the official documentation for more details on CORS configuration.
3. Verify the configuration (optional):
b2 bucket get my-bucketRequired CORS Operations
The S3 operations Sveltia CMS requires are:
s3_get— forListObjectsV2(listing) andGetObject(preview/download)s3_head— forHeadObject(metadata checks)s3_put— forPutObject(uploads)s3_delete— forDeleteObject(deletions)s3_post— for multipart uploads
B2 maps these native operations to the standard S3 HTTP methods (GET, HEAD, PUT, DELETE, POST).
Configuration
Here’s an example configuration for Backblaze B2:
media_libraries:
backblaze_b2:
access_key_id: 0123456789abcdef0123456789ab
bucket: my-bucket
region: us-east-005
prefix: cms-uploads/ # Optional
public_url: https://cdn.example.com # Optional, only for private buckets[media_libraries.backblaze_b2]
access_key_id = "0123456789abcdef0123456789ab"
bucket = "my-bucket"
region = "us-east-005"
prefix = "cms-uploads/"
public_url = "https://cdn.example.com"{
"media_libraries": {
"backblaze_b2": {
"access_key_id": "0123456789abcdef0123456789ab",
"bucket": "my-bucket",
"region": "us-east-005",
"prefix": "cms-uploads/",
"public_url": "https://cdn.example.com"
}
}
}{
media_libraries: {
backblaze_b2: {
access_key_id: '0123456789abcdef0123456789ab',
bucket: 'my-bucket',
region: 'us-east-005',
prefix: 'cms-uploads/', // Optional
public_url: 'https://cdn.example.com', // Optional
},
},
}WARNING
Do not write your Application Key (secret) in the configuration file, as it should be kept confidential and not exposed in client-side code. Users will be prompted to enter the key when they use the storage for the first time, which will be stored securely in the browser’s local storage.
Configuration Properties
| Property | Required | Description |
|---|---|---|
access_key_id | Yes | B2 Application Key ID (keyID). Safe to store in config. |
bucket | Yes | The B2 bucket name. |
region | Yes | B2 region, e.g. us-west-001, us-east-005, eu-central-003. See B2 regions list. |
prefix | No | Path prefix within the bucket, e.g. uploads/. |
public_url | No | CDN or custom domain URL for asset previews. Only required for private buckets. Public buckets serve objects directly via the S3 endpoint. |
Public Buckets vs. Private Buckets
Public Buckets (Recommended for Simplicity)
When a bucket is set to Public (allPublic), B2’s S3 endpoint serves objects anonymously without authentication. Asset URLs use the virtual-hosted storage endpoint:
https://{bucket}.s3.{region}.backblazeb2.com/{key}No public_url configuration is needed — previews and downloads work automatically.
Private Buckets (Requires CDN)
For private buckets, you must configure a public_url pointing to a CDN or proxy that provides public access to the objects. B2’s S3 API always requires authentication, so direct storage URLs won’t work for previews in the CMS.
public_url: 'https://cdn.example.com'WARNING
The storage endpoint is always used for listing and uploading operations regardless of the public_url setting. Only the asset preview/download URLs shown in the CMS change.
Content Security Policy
API calls (list, upload) go to https://s3.{region}.backblazeb2.com. For public buckets, asset URLs use https://{bucket}.s3.{region}.backblazeb2.com:
connect-src https://s3.us-east-005.backblazeb2.com;
img-src https://my-bucket.s3.us-east-005.backblazeb2.com;If using a private bucket with a CDN via public_url:
connect-src https://s3.us-east-005.backblazeb2.com;
img-src https://cdn.example.com;Replace us-east-005 and my-bucket with your actual region and bucket name.
See the CSP documentation for more details.
B2-Specific Notes
No Per-Object ACLs
B2’s S3 API does not support the x-amz-acl header for per-object access control. Visibility is controlled at the bucket level (public or private). Sveltia CMS automatically omits the x-amz-acl: public-read header when uploading to B2, so uploads work correctly regardless of bucket visibility.
Region Endpoint
B2 uses a region-specific endpoint for the S3 API (https://s3.{region}.backblazeb2.com), and asset URLs use virtual-hosted-style addressing (https://{bucket}.s3.{region}.backblazeb2.com/{key}) for public buckets. This is handled automatically by Sveltia CMS.
Accessing the Storage
The Backblaze B2 media storage can be accessed through the File and Image fields in Sveltia CMS. Enter your Application Key (secret) in the CMS UI when prompted, and you’ll be able to upload new media directly to B2 or select existing media from your bucket.
When uploading media, files will be stored in your B2 bucket with zero egress fees for downloads. You can also select existing media from your B2 storage.
Future Plans
You’ll be able to manage your B2 files directly from the Asset Library in future releases.