Skip to content

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:

  • listFiles
  • readFiles
  • writeFiles
  • deleteFiles

Using the B2 CLI:

sh
b2 key create --bucket my-bucket sveltia-cms listFiles,readFiles,writeFiles,deleteFiles

The 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:

sh
b2 bucket create my-bucket allPublic

INFO

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.

sh
b2 account authorize <adminKeyId> <adminKey>

2. Set the CORS rule with S3 operations:

sh
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 allPublic

Replace 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):

sh
b2 bucket get my-bucket

Required CORS Operations

The S3 operations Sveltia CMS requires are:

  • s3_get — for ListObjectsV2 (listing) and GetObject (preview/download)
  • s3_head — for HeadObject (metadata checks)
  • s3_put — for PutObject (uploads)
  • s3_delete — for DeleteObject (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:

yaml
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
toml
[media_libraries.backblaze_b2]
access_key_id = "0123456789abcdef0123456789ab"
bucket = "my-bucket"
region = "us-east-005"
prefix = "cms-uploads/"
public_url = "https://cdn.example.com"
json
{
  "media_libraries": {
    "backblaze_b2": {
      "access_key_id": "0123456789abcdef0123456789ab",
      "bucket": "my-bucket",
      "region": "us-east-005",
      "prefix": "cms-uploads/",
      "public_url": "https://cdn.example.com"
    }
  }
}
js
{
  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

PropertyRequiredDescription
access_key_idYesB2 Application Key ID (keyID). Safe to store in config.
bucketYesThe B2 bucket name.
regionYesB2 region, e.g. us-west-001, us-east-005, eu-central-003. See B2 regions list.
prefixNoPath prefix within the bucket, e.g. uploads/.
public_urlNoCDN 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

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.

yaml
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.

Released under the MIT License.