Skip to content

Azure Blob Storage Integration

Azure Blob Storage is Microsoft’s object storage service for unstructured data. Unlike most of the other object storage services Sveltia CMS supports, Blob Storage does not offer an S3-compatible API, so the CMS talks to the Blob Service REST API directly. Requests are authorized with a shared access signature (SAS) token, and files are uploaded straight from the browser to Azure — no backend proxy is required.

Requirements

  • An Azure storage account with a blob container created.
  • A SAS token with the Read, Write, Create and List permissions on that container (see Credentials below).
  • A CORS rule on the storage account’s Blob service (see CORS below).
  • A public_url configured, unless the container allows anonymous read access (see Public Read Access below).

CSP

If your site uses a Content Security Policy (CSP), you need to allow the Blob service endpoint and your public URL. See Content Security Policy below for details.

Setup

Credentials

Azure storage account keys can’t be scoped to a single container — they grant full control over the entire storage account — so Sveltia CMS uses a SAS token instead. A SAS is limited to the permissions and expiry you choose, and it’s the only credential the CMS needs.

Create a service SAS for the container via Azure Portal > Storage account > Data storage > Containers > [container] > Shared access tokens:

  • Signing method: Account key (or User delegation key; see the note below)
  • Permissions: Read, Create, Write, List
  • Expiry: as far out as your security policy allows (see Token Expiry below)
  • Allowed protocols: HTTPS only

Click Generate SAS token and URL and copy the Blob SAS token — the query string that starts with sv=, not the full URL below it.

An account SAS, created under Storage account > Security + networking > Shared access signature, works as well. It needs Allowed services: Blob, Allowed resource types: Container and Object, and the same permissions as above.

The token is entered by users in the CMS UI when they access the media library for the first time — it is never stored in config. See Accessing the Storage below.

Accounts that disallow Shared Key

If your storage account has Allow storage account key access disabled, neither a service SAS nor an account SAS signed with the account key will be accepted. Generate a user delegation SAS, which is signed with Microsoft Entra ID credentials instead:

sh
az storage container generate-sas \
  --account-name mystorageaccount \
  --name my-container \
  --permissions rcwl \
  --expiry 2026-12-31T00:00Z \
  --auth-mode login --as-user \
  --https-only --output tsv

A user delegation SAS is valid for a maximum of seven days.

Token Expiry

Every SAS token has an expiry date. Once it passes, the media library stops loading with an authorization error, and users need to generate a new token and enter it again in the CMS. Choose an expiry that balances your security policy against how often your editors want to repeat that step.

Public Read Access

Blob containers are private by default, and new storage accounts have anonymous access disabled at the account level. This matters because the URL Sveltia CMS writes into your entries can’t contain the SAS token — the token expires, and the URL would break with it.

Two options are available:

Option A — Anonymous read access on the container:

  1. In Storage account > Settings > Configuration, set Allow blob anonymous access to Enabled.
  2. In Containers > [container] > Change access level, choose Blob (anonymous read access for blobs only).

Asset URLs are then the blob endpoint URLs, and public_url is optional.

Option B — CDN or custom domain (recommended for production):

Put Azure CDN or Azure Front Door in front of the container, then set that hostname as public_url in your config:

yaml
public_url: 'https://media.example.com'

Asset URLs are constructed as {public_url}/{blob name}, using the full blob name, including any prefix.

Previews vs. stored URLs

When public_url is omitted, previews within the CMS still work against a private container, because the SAS token is appended to the preview URL. The URL saved into your entries is the plain blob URL without the token, so it only resolves for your site’s visitors if the container allows anonymous read access.

CORS

Configure cross-origin resource sharing under Storage account > Settings > Resource sharing (CORS) > Blob service. CORS is required because Sveltia CMS reads and writes blobs directly from the browser, and the x-ms-blob-type header it sends on uploads triggers a preflight request.

SettingValue
Allowed originshttps://your-cms-domain.com
Allowed methodsGET, HEAD, OPTIONS, PUT
Allowed headers* (or x-ms-blob-type,content-type)
Exposed headers*
Max age3600

The equivalent Azure CLI command:

sh
az storage cors add \
  --services b \
  --methods GET HEAD OPTIONS PUT \
  --origins https://your-cms-domain.com \
  --allowed-headers '*' \
  --exposed-headers '*' \
  --max-age 3600 \
  --account-name mystorageaccount

CORS rules are set per storage account, not per container, and they apply to the Blob service as a whole.

Configuration

Here’s an example configuration for Azure Blob Storage:

yaml
media_libraries:
  azure_blob_storage:
    account_name: mystorageaccount
    container: my-container
    public_url: https://media.example.com # Optional
    prefix: cms-uploads/ # Optional
toml
[media_libraries.azure_blob_storage]
account_name = "mystorageaccount"
container = "my-container"
public_url = "https://media.example.com" # Optional
prefix = "cms-uploads/" # Optional
json
{
  "media_libraries": {
    "azure_blob_storage": {
      "account_name": "mystorageaccount",
      "container": "my-container",
      "public_url": "https://media.example.com",
      "prefix": "cms-uploads/"
    }
  }
}
js
{
  media_libraries: {
    azure_blob_storage: {
      account_name: 'mystorageaccount',
      container: 'my-container',
      public_url: 'https://media.example.com', // Optional
      prefix: 'cms-uploads/', // Optional
    },
  },
}

WARNING

Do not write your SAS token in the configuration file, as it should be kept confidential and not exposed in client-side code. Users will be prompted to enter the token when they use the storage first time, which will be stored securely in the browser’s local storage.

Configuration Properties

PropertyRequiredDescription
account_nameYesThe storage account name. Used to construct the Blob service endpoint, https://{account_name}.blob.core.windows.net. Not required if endpoint is given.
containerYesThe blob container name.
public_urlNoPublic URL for asset downloads. Required unless the container allows anonymous read access, because the URL stored in your entries can’t contain the SAS token.
prefixNoPath prefix within the container, e.g. uploads/.
endpointNoCustom Blob service endpoint, including the account path where applicable, e.g. the Azurite emulator URL http://127.0.0.1:10000/devstoreaccount1. Overrides account_name.

Content Security Policy

Allow the Blob service endpoint for your storage account:

connect-src https://mystorageaccount.blob.core.windows.net;
img-src     https://mystorageaccount.blob.core.windows.net;

If you serve assets through a CDN or custom domain via public_url, use that host for img-src instead:

connect-src https://mystorageaccount.blob.core.windows.net;
img-src     https://media.example.com;

Replace mystorageaccount with your actual storage account name.

See the CSP documentation for more details.

Accessing the Storage

The Azure Blob Storage media storage can be accessed through the File and Image fields in Sveltia CMS. Enter your SAS token in the CMS UI when prompted — or at any time under Settings > Media > Cloud Storage Service API Keys — and you’ll be able to upload new media directly to Azure or select existing media from your container.

When uploading media, files are stored in your container as block blobs, and you can take advantage of Azure’s capabilities directly from the CMS. You can also select existing media from your Blob Storage.

Future Plans

You’ll be able to manage your Azure Blob Storage files directly from the Asset Library in future releases.