From 37957a4d9b103f50697ede4f2e9d9cab5acdb92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Garc=C3=ADa=20Montoro?= Date: Thu, 11 Jun 2026 11:05:45 +0200 Subject: [PATCH 01/10] MM-68718: Document Azure Blob Storage as a file storage backend (#8976) * Document Azure Blob Storage as a file storage backend Adds Azure Blob Storage to the File storage system reference: a new azureblob driver-name option and individual entries for the FileSettings.AzureStorageAccount, AzureContainer, AzurePathPrefix, AzureAccessKey, AzureEndpoint, AzureSSL, and AzureRequestTimeoutMilliseconds settings. Extends the dedicated export filestore list with the matching Export* variants. Calls out the restart-required behaviour when changing file storage settings so admins know Save in System Console isn't enough on its own. ------ AI assisted commit * Add walk-through page for configuring Azure Blob Storage Folds the full prereqs, Azure portal/CLI provisioning, System Console walk-through, Test Connection semantics, restart-required warning, verification, optional export backend, and troubleshooting sections into a dedicated configure/azure-blob-storage page. Wires the new page into the configuration-settings toctree and bullet list, and adds a seealso link from the File storage section of environment-configuration-settings so admins can find it from the reference page. ------ AI assisted commit * Document migrating existing files from Amazon S3 Adds a Migrate existing files from Amazon S3 section to the Azure Blob Storage walk-through. Covers the recommended trickle-then-cutover pattern (long rclone sync, short AzCopy maintenance window), the prerequisites for the migration host, phase-by-phase commands, verification queries (object count parity, sha256 spot-check), the rollback path, and caveats (S3 versioning, sync vs copy, prefix rewrites, cross-region cost, Storage Mover preview status). Updates the migration note under step 4 and the troubleshooting entry for missing pre-cutover files to cross-reference the new section. ------ AI assisted commit * Document AzureCloud and the updated AzureEndpoint semantics Adds the AzureCloud setting documentation (commercial/government/custom) to both the environment configuration reference and the Azure walkthrough, rewrites the AzureEndpoint entry to reflect its new role as the full Blob service URL valid only when AzureCloud is custom, and removes the stale note that said sovereign clouds aren't configured through the endpoint override. Adds ExportAzureCloud to the dedicated export filestore key list. ------ AI assisted commit * Document DefaultAzureCredential authentication mode Restructures Step 3 of the Azure Blob Storage walk-through to cover both shared-key and the new default_credential authentication mode. The default_credential subsection walks an admin through picking the identity source that matches the host (managed identity on Azure VM/App Service/AKS, workload identity, service principal, az login) and granting Storage Blob Data Contributor on the storage account. Updates Step 4 to describe the new "Azure authentication" dropdown in the System Console, including the conditional visibility of the Azure Storage account key field. Adds AuthorizationPermissionMismatch to the troubleshooting table and documents the propagation delay that follows a fresh role assignment. Adds FileSettings.AzureAuthMode to the environment-configuration reference and to the ExportAzure* list under the dedicated export filestore section. ------ AI assisted commit * Simplify the docs * Update source/administration-guide/configure/azure-blob-storage.rst Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Document Azure SAS support for presigned export downloads Add ExportAzurePresignExpiresSeconds to the dedicated export filestore key list, and generalize the presigned-download note so it reflects that exports can now be downloaded via an Azure Blob Storage SAS URL, not just an Amazon S3 presigned URL. ------ AI assisted commit * Address review comments * Add missing new line * Fix malformed quotes --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../configure/azure-blob-storage.rst | 217 +++++++++++++++++ .../environment-configuration-settings.rst | 224 +++++++++++++++++- 2 files changed, 437 insertions(+), 4 deletions(-) create mode 100644 source/administration-guide/configure/azure-blob-storage.rst diff --git a/source/administration-guide/configure/azure-blob-storage.rst b/source/administration-guide/configure/azure-blob-storage.rst new file mode 100644 index 00000000000..2a238454a3c --- /dev/null +++ b/source/administration-guide/configure/azure-blob-storage.rst @@ -0,0 +1,217 @@ +Configure Azure Blob Storage as the Mattermost file store +========================================================== + +.. include:: ../../_static/badges/all-commercial.rst + :start-after: :nosearch: + +Mattermost can store user uploads -- attachments, profile images, plugin assets, emoji, compliance exports -- in an Azure Storage account. This guide walks an administrator through the steps to provision the Azure side and point a Mattermost server at it via the System Console. + +Prerequisites +------------- + +- An Azure subscription with a storage account and a container already created. +- Either the Azure portal, or the `Azure CLI `__ (``az``) installed and signed in with ``az login``. Both are documented below. +- A Mattermost deployment (v11.9 or later) with System Console access for a System Admin account. + +If you plan to migrate existing files from another backend, take a backup of the current storage location (S3 bucket, local disk, etc.) before changing the configuration. Switching the file driver does not migrate existing files automatically. + +Step 1: Choose an authentication mode +------------------------------------- + +Mattermost supports two ways for the server to authenticate to Azure. Pick the one that fits how the server runs: + +- **Shared key**: the server signs each request with the :ref:`Storage Account access key `. Works anywhere Mattermost runs (on-premises, non-Azure cloud, local development) because it does not depend on the host having an Azure identity. The trade-off is that the key is a long-lived secret stored in ``config.json``. +- **Default credential (Microsoft Entra ID)**: the server obtains a token from Microsoft Entra ID and signs requests with it. No long-lived secret in Mattermost configuration. This is the recommended mode for deployments running on Azure, where the host environment already provides an identity (managed identity on Azure VM / App Service / AKS, workload identity for federated workloads, or a service principal). + +The Azure-side setup differs slightly between the two modes. Follow the subsection that matches your choice; you can switch modes later by changing the :ref:`Azure authentication ` setting in the System Console. + +Option A: Shared key +~~~~~~~~~~~~~~~~~~~~ + +Retrieve the Storage Account access key. + +**Azure portal** + +1. Open the storage account, then **Security + networking** > **Access keys**. +2. Select **Show** next to ``key1`` (or ``key2``) and copy the value. + +**Azure CLI** + +.. code-block:: bash + + az storage account keys list \ + --account-name acmemattermost \ + --resource-group mm-prod-files \ + --query "[0].value" -o tsv + +.. note:: + + Treat the shared key as a secret -- anyone with it has full access to the storage account (every container and all data it holds). A shared key can't be scoped to a single container, to specific operations, or to a resource group; if you need least-privilege access, use `Option B: Default credential (Microsoft Entra ID)`_ with a container-scoped **Storage Blob Data Contributor** role instead. Azure provides two keys so you can rotate without downtime: update Mattermost to ``key2``, regenerate ``key1``, then swap on the next rotation cycle. Plan a rotation cadence that matches your organisation's policy. + +Option B: Default credential (Microsoft Entra ID) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The server uses ``DefaultAzureCredential`` from the Azure SDK, which discovers a working identity at runtime in this order. The first source that returns a token is used. + +#. ``EnvironmentCredential`` -- service-principal environment variables. +#. ``WorkloadIdentityCredential`` -- federated workload identity. +#. ``ManagedIdentityCredential`` -- the platform-provided managed identity. +#. ``AzureCLICredential`` -- the signed-in ``az`` session, useful for local development. + +Whichever identity the SDK selects, **that** identity needs **Storage Blob Data Contributor** (or a custom role with the equivalent ``read/write/list/delete`` data-plane actions) on the storage account or container. Without it, ``TestConnection`` returns ``AuthorizationPermissionMismatch``. + +Pick the identity source that matches the host: + +.. list-table:: + :header-rows: 1 + :widths: 25 75 + + * - Host + - Identity source + * - Azure VM, App Service, AKS, Container Apps + - Assign a **system-assigned** or **user-assigned managed identity** to the compute resource. ``DefaultAzureCredential`` resolves to ``ManagedIdentityCredential`` with no extra configuration. For user-assigned identities, set ``AZURE_CLIENT_ID`` in the server's environment so the SDK picks the right one. + * - AKS with workload-identity federation + - Annotate the Mattermost ``ServiceAccount`` with the client ID and configure the OIDC issuer per the `AKS workload identity guide `__. ``DefaultAzureCredential`` resolves to ``WorkloadIdentityCredential``. + * - Non-Azure host or container + - Create a service principal and set ``AZURE_TENANT_ID``, ``AZURE_CLIENT_ID``, and ``AZURE_CLIENT_SECRET`` (or ``AZURE_CLIENT_CERTIFICATE_PATH``) in the server's environment. ``DefaultAzureCredential`` resolves to ``EnvironmentCredential``. + * - Local development on an admin's workstation + - Sign in with ``az login``. ``DefaultAzureCredential`` resolves to ``AzureCLICredential``. + +To prepare the account you're going to use, you'll need to assign the role from the Azure Portal or using the Azure CLI, as shown below (substitute the principal of the identity Mattermost will authenticate as): + +.. code-block:: bash + + STORAGE_ACCOUNT_ID=$(az storage account show \ + --name acmemattermost \ + --resource-group mm-prod-files \ + --query id -o tsv) + + # For a managed identity (system-assigned on a VM/App Service/AKS pod): + az role assignment create \ + --assignee-object-id "" \ + --assignee-principal-type ServicePrincipal \ + --role "Storage Blob Data Contributor" \ + --scope "$STORAGE_ACCOUNT_ID" + + # For a service principal: + az role assignment create \ + --assignee "" \ + --role "Storage Blob Data Contributor" \ + --scope "$STORAGE_ACCOUNT_ID" + +.. note:: + + Granting the role requires **User Access Administrator** or **Owner** on the storage account; ``Contributor`` is not enough. Plan to have an administrator with that role run the ``az role assignment create`` step. If you scope the role to a single container instead of the whole storage account, replace ``--scope "$STORAGE_ACCOUNT_ID"`` with ``--scope "$STORAGE_ACCOUNT_ID/blobServices/default/containers/"``. + +.. tip:: + + Azure RBAC role assignments can take 30-120 seconds to propagate. If the first ``TestConnection`` returns ``AuthorizationPermissionMismatch`` immediately after the role assignment, wait a minute and retry before assuming a misconfiguration. + +.. note:: + + Mattermost holds the credential, not the token. Microsoft Entra ID access tokens are short-lived, but the Azure SDK caches each token and refreshes it automatically before it expires, so routine token rotation never interrupts file access while the server is running. Access stops only if the underlying identity or its authorization changes or is removed. + +Step 2: Configure Mattermost +---------------------------- + +Sign in as a System Admin and open **System Console > Environment > File Storage**. + +1. **File storage system**: select **Azure Blob Storage**. The Azure-specific fields appear and the S3/local fields are hidden. +2. **Azure cloud**: select the Azure cloud that hosts the storage account: + + - **Azure Commercial** (default): the global Azure cloud (``{account}.blob.core.windows.net``). Only the storage account name is required. + - **Azure Government**: the US Government cloud (``{account}.blob.core.usgovcloudapi.net``). Only the storage account name is required. + - **Custom Endpoint**: any other Azure cloud (for example, Azure China), an Azurite emulator, or a reverse proxy. Provide the full Blob service URL via **Azure endpoint** below. + +3. **Azure Storage account**: the storage account name (for example, ``acmemattermost``). +4. **Azure container**: the container name (for example, ``mattermost``). +5. **Azure path prefix**: optional. Set this if you want Mattermost to write under a sub-path inside the container, for example ``prod/``. Leave empty to use the container root. +6. **Azure authentication**: select the mode you set up in step 1: + + - **Shared key** (default): Mattermost signs each request with the Storage Account access key. Choose this if you completed `Option A: Shared key`_. + - **Default credential (Microsoft Entra ID)**: Mattermost authenticates as the identity provided by the host environment. Choose this if you completed `Option B: Default credential (Microsoft Entra ID)`_. The **Azure Storage account key** field below is hidden because the access key is not used in this mode. + +7. **Azure Storage account key** (visible only when **Azure authentication** is **Shared key**): paste the shared key from `Option A: Shared key`_. +8. **Azure endpoint** (visible only when **Azure cloud** is set to **Custom Endpoint**): the full Blob service URL, including scheme and storage account. Mattermost passes this URL to the Azure SDK unchanged, so the storage account must already be embedded in the hostname (vhost-style, for example ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in the path (path-style, for example ``http://localhost:10000/devstoreaccount1/`` for Azurite). The chosen authentication mode signs against the host this URL points at, so the host must serve the storage account named above. +9. **Enable secure Azure Blob Storage connections** (visible only when **Azure cloud** is **Azure Commercial** or **Azure Government**): keep this enabled (the default). The Custom Endpoint cloud determines the scheme from the **Azure endpoint** URL, so this toggle is hidden for that mode. +10. **Azure request timeout (milliseconds)**: default is ``30000`` (30 seconds). Increase only if your network needs more time for large objects. + +Save the settings and click **Test Connection**. Mattermost issues a no-op write/read/delete against the configured container using the credentials submitted in the form. A green ``Connection was successful`` message confirms the credentials, container name, and endpoint all work. A red error message includes the underlying reason; common ones are listed in `Troubleshooting`_. + +.. warning:: + + **Restart required.** The Mattermost server caches the file storage backend at startup and does not re-create it when the file storage configuration changes. After saving, restart every Mattermost server in the deployment (``systemctl restart mattermost``, recycle the container, or roll the deployment in your cluster) for the new driver to take effect. **Test Connection** works before the restart because it builds a temporary backend from the submitted form values. + +.. warning:: + + Switching the file driver does **not** migrate existing files. If you are moving an existing deployment from Amazon S3, see `Migrate existing files from Amazon S3`_ below before changing the driver. For migrations from local disk, copy the directory contents into the Azure container using ``azcopy`` (`docs `__). In either case, files uploaded before the switch are unreachable once the driver changes unless they are present at the same key in the destination. + +Step 3: Verify +-------------- + +1. After the restart, reload the System Console or any channel. +2. Upload an attachment in any channel. A small image is a good test, because Mattermost stores three blobs for an image (original, preview, thumbnail), which exercises the upload path more thoroughly than a plain file. +3. The post should render the attachment and preview as usual. +4. In the Azure portal, open the container and confirm new blobs appeared under the path ``/teams//channels//users///`` (the same layout the local-disk and S3 backends use). For an image you will see ``.``, ``_preview.``, and ``_thumb.``. + +Migrate existing files from Amazon S3 +------------------------------------- + +If you are switching an existing deployment from S3 to Azure Blob Storage, the file content must be present in the Azure container at the same key Mattermost would have written to. Mattermost itself does not move files between backends, so this is an out-of-band copy that you run once before flipping the driver. + +Mattermost writes blobs at the same relative path on every backend: + +.. code-block:: text + + {path-prefix}/{YYYYMMDD}/teams/{teamID}/channels/{channelID}/users/{userID}/{fileID}/{filename} + +This means a straight key-for-key copy from the S3 bucket to the Azure container is sufficient. If you use ``AmazonS3PathPrefix`` on the S3 side, set ``AzurePathPrefix`` to the same value on the Azure side (or rewrite the prefix during the copy). + +There are multiple ways to accomplish this. The recommended way is using the `Azure Storage Mover service `__, which provides a cloud-to-cloud migration from Amazon S3 to Azure Blob Storage. + +There are alternative tools that can also help, like `rclone `__ and `AzCopy `__. + +(Optional) Configure the export backend +--------------------------------------- + +Compliance and data exports can be stored separately from regular file uploads. The **File Storage (Exports)** section directly below **File Storage** in the System Console mirrors the fields above and accepts the same Azure credentials. Customers typically point exports at a different container (or a different account) so the export retention policy can differ from regular uploads. The export target is an independent backend with its own driver and credentials, so it doesn't have to use the same provider as regular uploads; e.g., you can keep uploads on Amazon S3 and send exports to Azure Blob Storage, or the reverse. + +See :ref:`Enable dedicated export filestore target ` for the full list of ``ExportAzure*`` keys. + +Troubleshooting +--------------- + +.. list-table:: + :header-rows: 1 + :widths: 35 65 + + * - Symptom + - Likely cause + * - ``AuthenticationFailed`` on **Test Connection** + - When **Azure authentication** is **Shared key**: wrong account name or shared key. Confirm both in the **Access keys** blade of the Azure portal. When **Azure authentication** is **Default credential**: no identity source was available -- the host has no managed identity, the workload-identity federation is not set up, and no ``AZURE_TENANT_ID`` / ``AZURE_CLIENT_ID`` / ``AZURE_CLIENT_SECRET`` environment variables are set. + * - ``AuthorizationPermissionMismatch`` on **Test Connection** + - Only applies when **Azure authentication** is **Default credential**. The identity the SDK selected does not hold a data-plane role on the storage account. Grant **Storage Blob Data Contributor** to that identity per `Option B: Default credential (Microsoft Entra ID)`_, then wait 30-120 seconds for the role assignment to propagate. + * - ``ContainerNotFound`` + - Container name is wrong or was created under a different storage account. + * - ``connection refused`` or TLS errors + - When **Azure cloud** is **Custom Endpoint**, the **Azure endpoint** URL points at a host that isn't reachable or uses the wrong scheme. When **Azure cloud** is **Azure Commercial** or **Azure Government**, **Enable secure Azure Blob Storage connections** is disabled in front of a TLS-only destination. + * - **Test Connection** succeeds but uploads in channels fail + - Check **System Console > Reporting > Server Logs** for the Azure error returned by the SDK. The most common cause is a forgotten server restart after **Save**. + * - Files uploaded before the switch are no longer visible + - The existing files are still on the previous backend. For S3 migrations, follow `Migrate existing files from Amazon S3`_ to copy the bucket into the Azure container at matching keys. For other backends, copy the contents into the Azure container with ``azcopy`` (or equivalent) and confirm the destination path matches the layout Mattermost uses. + +Reference +--------- + +Each Azure setting is documented in detail in :ref:`Environment configuration settings `: + +- :ref:`File storage system ` (``FileSettings.DriverName``) +- :ref:`Azure Storage account ` (``FileSettings.AzureStorageAccount``) +- :ref:`Azure container ` (``FileSettings.AzureContainer``) +- :ref:`Azure path prefix ` (``FileSettings.AzurePathPrefix``) +- :ref:`Azure authentication ` (``FileSettings.AzureAuthMode``) +- :ref:`Azure Storage account key ` (``FileSettings.AzureAccessKey``) +- :ref:`Azure cloud ` (``FileSettings.AzureCloud``) +- :ref:`Azure endpoint ` (``FileSettings.AzureEndpoint``) +- :ref:`Enable secure Azure Blob Storage connections ` (``FileSettings.AzureSSL``) +- :ref:`Azure request timeout ` (``FileSettings.AzureRequestTimeoutMilliseconds``) diff --git a/source/administration-guide/configure/environment-configuration-settings.rst b/source/administration-guide/configure/environment-configuration-settings.rst index e3a47df768d..5db975b32fa 100644 --- a/source/administration-guide/configure/environment-configuration-settings.rst +++ b/source/administration-guide/configure/environment-configuration-settings.rst @@ -2000,7 +2000,11 @@ With self-hosted deployments, you can configure file storage settings by going t .. note:: - Mattermost currently supports storing files on the local filesystem and Amazon S3 or S3-compatible containers. We have tested Mattermost with `Digital Ocean Spaces `__, but not all S3-compatible containers on the market. If you are looking to use other S3-compatible containers, we recommend completing your own testing. You can also use local storage or a network drive using NFS. + Mattermost supports storing files on the local filesystem, Amazon S3 or S3-compatible containers, and Azure Blob Storage. We have tested Mattermost with `Digital Ocean Spaces `__, but not all S3-compatible containers on the market. If you are looking to use other S3-compatible containers, we recommend completing your own testing. You can also use local storage or a network drive using NFS. + +.. seealso:: + + For a step-by-step walk-through covering Azure resource provisioning, System Console configuration, and verification, see :doc:`Configure Azure Blob Storage as the Mattermost file store `. .. config:setting:: file-storage-system :displayname: File storage system (File Storage) @@ -2011,13 +2015,14 @@ With self-hosted deployments, you can configure file storage settings by going t - **local**: **(Default)** Files and images are stored in the specified local file directory. - **amazons3**: Files and images are stored on Amazon S3 based on the access key, bucket, and region fields provided. + - **azureblob**: Files and images are stored on Azure Blob Storage based on the storage account, key, and container fields provided. File storage system ~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------------------+-----------------------------------------------------------------------------+ | The type of file storage system used. | - System Config path: **Environment > File Storage** | -| Can be either Local File System or Amazon S3. | - ``config.json`` setting: ``FileSettings`` > ``DriverName`` > ``"local"`` | +| Can be Local File System, Amazon S3, or Azure Blob Storage. | - ``config.json`` setting: ``FileSettings`` > ``DriverName`` > ``"local"`` | | | - Environment variable: ``MM_FILESETTINGS_DRIVERNAME`` | | - **local**: **(Default)** Files and images are stored in | | | the specified local file directory. | | @@ -2025,8 +2030,15 @@ File storage system | based on the access key, bucket, and region fields | | | provided. The driver is compatible with other S3-compatible | | | services, such as Digital Ocean Spaces. | | +| - **azureblob**: Files and images are stored on Azure Blob | | +| Storage based on the storage account name, shared key, and | | +| container fields provided. | | +---------------------------------------------------------------+-----------------------------------------------------------------------------+ +.. note:: + + After saving a new file storage system, restart every Mattermost server in the deployment for the change to take effect. The file storage backend is initialized at startup and isn't rebuilt automatically when ``FileSettings`` change at runtime. + .. config:setting:: local-storage-directory :displayname: Local storage directory (File Storage) :systemconsole: Environment > File Storage @@ -2474,6 +2486,200 @@ Amazon S3 request timeout | Default is 30000 (30 seconds). | | +---------------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +.. config:setting:: azure-storage-account + :displayname: Azure Storage account (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureStorageAccount + :environment: MM_FILESETTINGS_AZURESTORAGEACCOUNT + :description: The name of your Azure Storage account. + +Azure Storage account +~~~~~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| The name of your Azure Storage account. | - System Config path: **Environment > File Storage** | +| | - ``config.json`` setting: ``FileSettings`` > ``AzureStorageAccount`` | +| A string with the storage account name as it appears in the | - Environment variable: ``MM_FILESETTINGS_AZURESTORAGEACCOUNT`` | +| Azure portal. Must be 3-24 lowercase letters and numbers. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-container + :displayname: Azure container (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureContainer + :environment: MM_FILESETTINGS_AZURECONTAINER + :description: The name of the container in your Azure Storage account. + +Azure container +~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| The name of the container in your Azure Storage account | - System Config path: **Environment > File Storage** | +| where Mattermost stores uploads. | - ``config.json`` setting: ``FileSettings`` > ``AzureContainer`` | +| | - Environment variable: ``MM_FILESETTINGS_AZURECONTAINER`` | +| A string with the container name. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-path-prefix + :displayname: Azure path prefix (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzurePathPrefix + :environment: MM_FILESETTINGS_AZUREPATHPREFIX + :description: An optional path prefix to use for blobs in your Azure container. Leave empty to write at the container root. + +Azure path prefix +~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| An optional path prefix to use for blobs in your Azure | - System Config path: **Environment > File Storage** | +| container. | - ``config.json`` setting: ``FileSettings`` > ``AzurePathPrefix`` | +| | - Environment variable: ``MM_FILESETTINGS_AZUREPATHPREFIX`` | +| A string containing the path prefix. Leave empty to write at | | +| the container root. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-authentication + :displayname: Azure authentication (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureAuthMode + :environment: MM_FILESETTINGS_AZUREAUTHMODE + :description: Selects how Mattermost authenticates to Azure. One of ``shared_key`` (default) or ``default_credential``. + +Azure authentication +~~~~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| Selects how Mattermost authenticates to the Azure Storage | - System Config path: **Environment > File Storage** | +| account. | - ``config.json`` setting: ``FileSettings`` > ``AzureAuthMode`` | +| | - Environment variable: ``MM_FILESETTINGS_AZUREAUTHMODE`` | +| - ``shared_key``: **(Default)** Mattermost signs requests | | +| with the Storage Account access key in | | +| ``FileSettings.AzureAccessKey``. Works for any deployment | | +| (on-premises, non-Azure cloud, local development). | | +| - ``default_credential``: Mattermost obtains an Entra ID | | +| token via the Azure SDK's ``DefaultAzureCredential`` chain | | +| (managed identity, workload identity, service-principal | | +| environment variables, or ``az login`` -- in that order) | | +| and signs requests with it. ``FileSettings.AzureAccessKey`` | | +| is ignored. Recommended for deployments on Azure where the | | +| host already provides a managed identity. | | +| | | +| The identity the SDK selects must hold **Storage Blob | | +| Data Contributor** (or equivalent) on the storage account | | +| or container. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-storage-account-key + :displayname: Azure Storage account key (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureAccessKey + :environment: MM_FILESETTINGS_AZUREACCESSKEY + :description: The shared key for your Azure Storage account. Used only when ``FileSettings.AzureAuthMode`` is ``shared_key``. + +Azure Storage account key +~~~~~~~~~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| The shared key for your Azure Storage account. Used only | - System Config path: **Environment > File Storage** | +| when ``FileSettings.AzureAuthMode`` is ``shared_key``. | - ``config.json`` setting: ``FileSettings`` > ``AzureAccessKey`` | +| Find this value in the Azure portal under your storage | - Environment variable: ``MM_FILESETTINGS_AZUREACCESSKEY`` | +| account's **Security + networking > Access keys** blade. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. note:: + + Treat the shared key as a secret. Azure provides two keys to support rotation without downtime: update Mattermost to one key, regenerate the other, then swap on the next rotation cycle. + +.. config:setting:: azure-cloud + :displayname: Azure cloud (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureCloud + :environment: MM_FILESETTINGS_AZURECLOUD + :description: Selects which Azure cloud hosts the storage account. One of ``commercial`` (default), ``government``, or ``custom``. + +Azure cloud +~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| Selects which Azure cloud Mattermost connects to. The choice | - System Config path: **Environment > File Storage** | +| determines which host the Azure SDK signs requests against. | - ``config.json`` setting: ``FileSettings`` > ``AzureCloud`` | +| | - Environment variable: ``MM_FILESETTINGS_AZURECLOUD`` | +| - ``commercial``: **(Default)** Vhost-style against | | +| ``{account}.blob.core.windows.net``. Only the storage | | +| account name is required. | | +| - ``government``: Vhost-style against | | +| ``{account}.blob.core.usgovcloudapi.net`` (Azure | | +| Government). Only the storage account name is required. | | +| - ``custom``: Mattermost uses the value of | | +| ``FileSettings.AzureEndpoint`` as the full Blob service | | +| URL. Use this for Azurite, reverse proxies, Azure China, or | | +| any other Azure cloud that doesn't have a built-in preset. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-endpoint + :displayname: Azure endpoint (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureEndpoint + :environment: MM_FILESETTINGS_AZUREENDPOINT + :description: Full Blob service URL used when ``FileSettings.AzureCloud`` is ``custom``. Ignored for the ``commercial`` and ``government`` clouds. + +Azure endpoint +~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| Full Blob service URL, including scheme and storage account. | - System Config path: **Environment > File Storage** | +| Used only when ``FileSettings.AzureCloud`` is ``custom``; | - ``config.json`` setting: ``FileSettings`` > ``AzureEndpoint`` | +| ignored for the ``commercial`` and ``government`` clouds | - Environment variable: ``MM_FILESETTINGS_AZUREENDPOINT`` | +| (which derive the URL from the storage account name). | | +| | | +| Mattermost passes this URL to the Azure SDK unchanged, so | | +| the storage account must already be embedded in the hostname | | +| (vhost-style, for example | | +| ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in | | +| the path (path-style, for example | | +| ``http://localhost:10000/devstoreaccount1/`` for Azurite). | | +| Shared-key auth signs against the host this URL points at, so | | +| make sure it actually serves the storage account configured | | +| in ``FileSettings.AzureStorageAccount``. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: enable-secure-azure-blob-storage-connections + :displayname: Enable secure Azure Blob Storage connections (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureSSL + :environment: MM_FILESETTINGS_AZURESSL + :description: Enable or disable secure Azure Blob Storage connections. Default value is **true**. + +Enable secure Azure Blob Storage connections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+--------------------------------------------------------------------------+ +| Enable or disable secure connections to Azure Blob Storage. | - System Config path: **Environment > File Storage** | +| | - ``config.json`` setting: ``FileSettings`` > ``AzureSSL`` > ``true`` | +| - **true**: **(Default)** Enables only secure Azure Blob | - Environment variable: ``MM_FILESETTINGS_AZURESSL`` | +| Storage connections. | | +| - **false**: Allows insecure connections. Only set to | | +| **false** when pointing at a local emulator without TLS. | | ++---------------------------------------------------------------+--------------------------------------------------------------------------+ + +.. config:setting:: azure-request-timeout + :displayname: Azure request timeout (File Storage) + :systemconsole: Environment > File Storage + :configjson: .FileSettings.AzureRequestTimeoutMilliseconds + :environment: MM_FILESETTINGS_AZUREREQUESTTIMEOUTMILLISECONDS + :description: Amount of time, in milliseconds, before requests to Azure Blob Storage time out. Default value is 30000 (30 seconds). + +Azure request timeout +~~~~~~~~~~~~~~~~~~~~~ + ++---------------------------------------------------------------+-----------------------------------------------------------------------------------------------+ +| The amount of time, in milliseconds, before requests to | - System Config path: **Environment > File Storage** | +| Azure Blob Storage time out. | - ``config.json`` setting: ``FileSettings`` > ``AzureRequestTimeoutMilliseconds`` > ``30000`` | +| | - Environment variable: ``MM_FILESETTINGS_AZUREREQUESTTIMEOUTMILLISECONDS`` | +| Default is 30000 (30 seconds). Increase only if your network | | +| needs more time for large objects. | | ++---------------------------------------------------------------+-----------------------------------------------------------------------------------------------+ + .. config:setting:: initial-font :displayname: Initial font (File Storage) :systemconsole: N/A @@ -4788,6 +4994,16 @@ Enable dedicated export filestore target | - ``ExportAmazonS3Trace`` | | | - ``ExportAmazonS3RequestTimeoutMilliseconds`` | | | - ``ExportAmazonS3PresignExpiresSeconds`` | | +| - ``ExportAzureStorageAccount`` | | +| - ``ExportAzureAuthMode`` | | +| - ``ExportAzureAccessKey`` | | +| - ``ExportAzureContainer`` | | +| - ``ExportAzurePathPrefix`` | | +| - ``ExportAzureCloud`` | | +| - ``ExportAzureEndpoint`` | | +| - ``ExportAzureSSL`` | | +| - ``ExportAzureRequestTimeoutMilliseconds`` | | +| - ``ExportAzurePresignExpiresSeconds`` | | | | | | - **False**: (**Default**) Standard | | | :ref:`file storage | | @@ -4798,5 +5014,5 @@ Enable dedicated export filestore target .. note:: - - When an alternate filestore target is configured, Mattermost Cloud admins can generate an S3 presigned URL for exports using the ``/exportlink [job-id|zip file|latest]`` slash command. See the :ref:`Mattermost data migration ` documentation for details. Alternatively, Cloud and self-hosted admins can use the :ref:`mmctl export generate-presigned-url ` command to generate a presigned URL directly from mmctl. - - Generating an S3 presigned URL requires the feature flag ``EnableExportDirectDownload`` to be set to ``true``, the storage must be compatible with generating an S3 link, and this experimental configuration setting must be set to ``true``. Presigned URLs for exports aren't supported for systems with shared storage. + - When an alternate filestore target is configured, Mattermost Cloud admins can generate a presigned download URL for exports using the ``/exportlink [job-id|zip file|latest]`` slash command. On Amazon S3 this is an S3 presigned URL; on Azure Blob Storage it's a Shared Access Signature (SAS) URL. The lifetimes of these URLs are controlled, respectively, by ``ExportAmazonS3PresignExpiresSeconds`` or ``ExportAzurePresignExpiresSeconds``. See the :ref:`Mattermost data migration ` documentation for details. Alternatively, Cloud and self-hosted admins can use the :ref:`mmctl export generate-presigned-url ` command to generate a presigned URL directly from mmctl. + - Generating a presigned URL requires the feature flag ``EnableExportDirectDownload`` to be set to ``true``, the storage must support presigned links (Amazon S3 or Azure Blob Storage), and this experimental configuration setting must be set to ``true``. Presigned URLs for exports aren't supported for systems with shared storage. From eb35cdac9bc9903a93b761338d165d4d0c1cfced Mon Sep 17 00:00:00 2001 From: Wayne Wollesen <50209602+ewwollesen@users.noreply.github.com> Date: Thu, 11 Jun 2026 08:58:28 -0500 Subject: [PATCH 02/10] docs: clarify ID attribute case sensitivity for AD/LDAP and SAML (#9020) Add notes to the AD/LDAP ID attribute, AD/LDAP Group ID attribute, and SAML ID attribute settings explaining that values are matched verbatim with no case normalization. Under PostgreSQL's default case-sensitive collation, a change in casing is treated as a new user or unlinked group, so the identity provider must return these attributes with consistent casing. Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: Katie Wiersgalla <39744472+wiersgallak@users.noreply.github.com> --- .../configure/authentication-configuration-settings.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index f9e68d6b7cf..9052f3087d9 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -821,6 +821,9 @@ ID attribute .. note:: If a user's ID Attribute changes, a new Mattermost account is created that is not associated with the previous account. If you need to change this field after users have signed-in, use the :ref:`mmctl ldap idmigrate ` command. +.. note:: + The ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing is treated as a new user and a separate account is created. Ensure your AD/LDAP server returns this attribute with consistent casing. + .. config:setting:: login-id-attribute :displayname: Login ID attribute (AD/LDAP > Account Synchronization) :systemconsole: Authentication > AD/LDAP @@ -1029,6 +1032,9 @@ Group ID attribute .. note:: This attribute is only used when AD/LDAP Group Sync is enabled and it is **required**. See the :doc:`AD/LDAP Group Sync documentation ` for more information. +.. note:: + The Group ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing means Mattermost no longer recognizes the previously synced group and treats it as a new, unlinked group. Ensure your AD/LDAP server returns this attribute with consistent casing. + Synchronization performance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1555,6 +1561,9 @@ Id attribute | String input. | - Environment variable: ``MM_SAMLSETTINGS_IDATTRIBUTE`` | +----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+ +.. note:: + The ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing is treated as a new user and a separate account is created. Ensure your identity provider returns this attribute with consistent casing. + .. config:setting:: guest-attribute :displayname: Guest attribute (SAML) :systemconsole: Authentication > SAML 2.0 From 53bc6d175d9c967c9ec9fb8d94f0eb2b4d7055cd Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 04:06:56 +0000 Subject: [PATCH 03/10] docs: add Edit Attachments permission documentation Document the new Edit Attachments permission introduced in Mattermost v11.8.0, which controls whether users can add or remove file attachments when editing posts. Co-authored-by: Combs7th Co-Authored-By: Claude Opus 4.8 (1M context) --- .../onboard/advanced-permissions.rst | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/administration-guide/onboard/advanced-permissions.rst b/source/administration-guide/onboard/advanced-permissions.rst index 198965eb095..2a93b5222a2 100644 --- a/source/administration-guide/onboard/advanced-permissions.rst +++ b/source/administration-guide/onboard/advanced-permissions.rst @@ -203,6 +203,26 @@ Example: As the default for the entire system, only allow users to edit their ow 3. In the **All Members**, **Channel Administrators**, and **Team Administrators** panels, in the **Manage Posts** section, check the box for **Edit Posts**. 4. From any panel, select the gear button to set the global time limit to ``300`` seconds. +Restrict who can edit post attachments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +From Mattermost v11.8, system admins can use the **Edit Attachments** permission to control whether users can add or remove file attachments when editing posts. + +The **Edit Attachments** permission is separate from **Edit Own Posts**. Users with permission to edit a post can still update the post text, but they can't add or remove file attachments unless **Edit Attachments** is also enabled. + +By default, **Edit Attachments** is granted to users who have permission to edit posts. + +To allow users to edit post text without changing attachments: + +1. Go to **System Console > User Management > Permissions**. +2. Select **Edit Scheme**. +3. In the applicable role panel, go to **Manage Posts**. +4. Enable **Edit Own Posts**. +5. Disable **Edit Attachments**. +6. Select **Save**. + +If a user sees **Post attachments cannot be edited** when editing a post, they don't have permission to add or remove attachments for that post. + Integration management ~~~~~~~~~~~~~~~~~~~~~~ From a0ffbb4f7fdbfb1be1fcf2dcb5306d35c767dbdc Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:22:36 -0700 Subject: [PATCH 04/10] Update authentication-configuration-settings.rst --- .../authentication-configuration-settings.rst | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index 9052f3087d9..d5c08d6fd0b 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -821,9 +821,6 @@ ID attribute .. note:: If a user's ID Attribute changes, a new Mattermost account is created that is not associated with the previous account. If you need to change this field after users have signed-in, use the :ref:`mmctl ldap idmigrate ` command. -.. note:: - The ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing is treated as a new user and a separate account is created. Ensure your AD/LDAP server returns this attribute with consistent casing. - .. config:setting:: login-id-attribute :displayname: Login ID attribute (AD/LDAP > Account Synchronization) :systemconsole: Authentication > AD/LDAP @@ -1032,9 +1029,6 @@ Group ID attribute .. note:: This attribute is only used when AD/LDAP Group Sync is enabled and it is **required**. See the :doc:`AD/LDAP Group Sync documentation ` for more information. -.. note:: - The Group ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing means Mattermost no longer recognizes the previously synced group and treats it as a new, unlinked group. Ensure your AD/LDAP server returns this attribute with consistent casing. - Synchronization performance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1561,9 +1555,6 @@ Id attribute | String input. | - Environment variable: ``MM_SAMLSETTINGS_IDATTRIBUTE`` | +----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+ -.. note:: - The ID attribute value is matched verbatim - Mattermost applies no case normalization. With PostgreSQL's default case-sensitive collation, a change in casing is treated as a new user and a separate account is created. Ensure your identity provider returns this attribute with consistent casing. - .. config:setting:: guest-attribute :displayname: Guest attribute (SAML) :systemconsole: Authentication > SAML 2.0 @@ -2717,4 +2708,4 @@ Enable guest magic link authentication +-------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------+ .. note:: - See the :ref:`guest accounts ` documentation for guest user setup details. \ No newline at end of file + See the :ref:`guest accounts ` documentation for guest user setup details. From bf31b544759dfb4d03df642c101be6eb5b6912f6 Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:23:58 -0700 Subject: [PATCH 05/10] Update authentication-configuration-settings.rst --- .../configure/authentication-configuration-settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index d5c08d6fd0b..bf2f58ead4f 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -2708,4 +2708,4 @@ Enable guest magic link authentication +-------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------+ .. note:: - See the :ref:`guest accounts ` documentation for guest user setup details. +See the :ref:`guest accounts ` documentation for guest user setup details. From dfe7533779a166844f41a9012b91d67f2c5256af Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:24:32 -0700 Subject: [PATCH 06/10] Update authentication-configuration-settings.rst --- .../configure/authentication-configuration-settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index bf2f58ead4f..3f3b4ec8ff0 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -2708,4 +2708,4 @@ Enable guest magic link authentication +-------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------+ .. note:: -See the :ref:`guest accounts ` documentation for guest user setup details. + See the :ref:`guest accounts ` documentation for guest user setup details. From 10ec3e91a011af580f41ba633fe2d3c181f67d6f Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:25:11 -0700 Subject: [PATCH 07/10] Update authentication-configuration-settings.rst --- .../configure/authentication-configuration-settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index 3f3b4ec8ff0..d5c08d6fd0b 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -2708,4 +2708,4 @@ Enable guest magic link authentication +-------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------+ .. note:: - See the :ref:`guest accounts ` documentation for guest user setup details. + See the :ref:`guest accounts ` documentation for guest user setup details. From c27728da82d3219132bbdd50228fe25d8f72927c Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:30:21 -0700 Subject: [PATCH 08/10] Update azure-blob-storage.rst --- .../configure/azure-blob-storage.rst | 216 ------------------ 1 file changed, 216 deletions(-) diff --git a/source/administration-guide/configure/azure-blob-storage.rst b/source/administration-guide/configure/azure-blob-storage.rst index 2a238454a3c..8b137891791 100644 --- a/source/administration-guide/configure/azure-blob-storage.rst +++ b/source/administration-guide/configure/azure-blob-storage.rst @@ -1,217 +1 @@ -Configure Azure Blob Storage as the Mattermost file store -========================================================== -.. include:: ../../_static/badges/all-commercial.rst - :start-after: :nosearch: - -Mattermost can store user uploads -- attachments, profile images, plugin assets, emoji, compliance exports -- in an Azure Storage account. This guide walks an administrator through the steps to provision the Azure side and point a Mattermost server at it via the System Console. - -Prerequisites -------------- - -- An Azure subscription with a storage account and a container already created. -- Either the Azure portal, or the `Azure CLI `__ (``az``) installed and signed in with ``az login``. Both are documented below. -- A Mattermost deployment (v11.9 or later) with System Console access for a System Admin account. - -If you plan to migrate existing files from another backend, take a backup of the current storage location (S3 bucket, local disk, etc.) before changing the configuration. Switching the file driver does not migrate existing files automatically. - -Step 1: Choose an authentication mode -------------------------------------- - -Mattermost supports two ways for the server to authenticate to Azure. Pick the one that fits how the server runs: - -- **Shared key**: the server signs each request with the :ref:`Storage Account access key `. Works anywhere Mattermost runs (on-premises, non-Azure cloud, local development) because it does not depend on the host having an Azure identity. The trade-off is that the key is a long-lived secret stored in ``config.json``. -- **Default credential (Microsoft Entra ID)**: the server obtains a token from Microsoft Entra ID and signs requests with it. No long-lived secret in Mattermost configuration. This is the recommended mode for deployments running on Azure, where the host environment already provides an identity (managed identity on Azure VM / App Service / AKS, workload identity for federated workloads, or a service principal). - -The Azure-side setup differs slightly between the two modes. Follow the subsection that matches your choice; you can switch modes later by changing the :ref:`Azure authentication ` setting in the System Console. - -Option A: Shared key -~~~~~~~~~~~~~~~~~~~~ - -Retrieve the Storage Account access key. - -**Azure portal** - -1. Open the storage account, then **Security + networking** > **Access keys**. -2. Select **Show** next to ``key1`` (or ``key2``) and copy the value. - -**Azure CLI** - -.. code-block:: bash - - az storage account keys list \ - --account-name acmemattermost \ - --resource-group mm-prod-files \ - --query "[0].value" -o tsv - -.. note:: - - Treat the shared key as a secret -- anyone with it has full access to the storage account (every container and all data it holds). A shared key can't be scoped to a single container, to specific operations, or to a resource group; if you need least-privilege access, use `Option B: Default credential (Microsoft Entra ID)`_ with a container-scoped **Storage Blob Data Contributor** role instead. Azure provides two keys so you can rotate without downtime: update Mattermost to ``key2``, regenerate ``key1``, then swap on the next rotation cycle. Plan a rotation cadence that matches your organisation's policy. - -Option B: Default credential (Microsoft Entra ID) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The server uses ``DefaultAzureCredential`` from the Azure SDK, which discovers a working identity at runtime in this order. The first source that returns a token is used. - -#. ``EnvironmentCredential`` -- service-principal environment variables. -#. ``WorkloadIdentityCredential`` -- federated workload identity. -#. ``ManagedIdentityCredential`` -- the platform-provided managed identity. -#. ``AzureCLICredential`` -- the signed-in ``az`` session, useful for local development. - -Whichever identity the SDK selects, **that** identity needs **Storage Blob Data Contributor** (or a custom role with the equivalent ``read/write/list/delete`` data-plane actions) on the storage account or container. Without it, ``TestConnection`` returns ``AuthorizationPermissionMismatch``. - -Pick the identity source that matches the host: - -.. list-table:: - :header-rows: 1 - :widths: 25 75 - - * - Host - - Identity source - * - Azure VM, App Service, AKS, Container Apps - - Assign a **system-assigned** or **user-assigned managed identity** to the compute resource. ``DefaultAzureCredential`` resolves to ``ManagedIdentityCredential`` with no extra configuration. For user-assigned identities, set ``AZURE_CLIENT_ID`` in the server's environment so the SDK picks the right one. - * - AKS with workload-identity federation - - Annotate the Mattermost ``ServiceAccount`` with the client ID and configure the OIDC issuer per the `AKS workload identity guide `__. ``DefaultAzureCredential`` resolves to ``WorkloadIdentityCredential``. - * - Non-Azure host or container - - Create a service principal and set ``AZURE_TENANT_ID``, ``AZURE_CLIENT_ID``, and ``AZURE_CLIENT_SECRET`` (or ``AZURE_CLIENT_CERTIFICATE_PATH``) in the server's environment. ``DefaultAzureCredential`` resolves to ``EnvironmentCredential``. - * - Local development on an admin's workstation - - Sign in with ``az login``. ``DefaultAzureCredential`` resolves to ``AzureCLICredential``. - -To prepare the account you're going to use, you'll need to assign the role from the Azure Portal or using the Azure CLI, as shown below (substitute the principal of the identity Mattermost will authenticate as): - -.. code-block:: bash - - STORAGE_ACCOUNT_ID=$(az storage account show \ - --name acmemattermost \ - --resource-group mm-prod-files \ - --query id -o tsv) - - # For a managed identity (system-assigned on a VM/App Service/AKS pod): - az role assignment create \ - --assignee-object-id "" \ - --assignee-principal-type ServicePrincipal \ - --role "Storage Blob Data Contributor" \ - --scope "$STORAGE_ACCOUNT_ID" - - # For a service principal: - az role assignment create \ - --assignee "" \ - --role "Storage Blob Data Contributor" \ - --scope "$STORAGE_ACCOUNT_ID" - -.. note:: - - Granting the role requires **User Access Administrator** or **Owner** on the storage account; ``Contributor`` is not enough. Plan to have an administrator with that role run the ``az role assignment create`` step. If you scope the role to a single container instead of the whole storage account, replace ``--scope "$STORAGE_ACCOUNT_ID"`` with ``--scope "$STORAGE_ACCOUNT_ID/blobServices/default/containers/"``. - -.. tip:: - - Azure RBAC role assignments can take 30-120 seconds to propagate. If the first ``TestConnection`` returns ``AuthorizationPermissionMismatch`` immediately after the role assignment, wait a minute and retry before assuming a misconfiguration. - -.. note:: - - Mattermost holds the credential, not the token. Microsoft Entra ID access tokens are short-lived, but the Azure SDK caches each token and refreshes it automatically before it expires, so routine token rotation never interrupts file access while the server is running. Access stops only if the underlying identity or its authorization changes or is removed. - -Step 2: Configure Mattermost ----------------------------- - -Sign in as a System Admin and open **System Console > Environment > File Storage**. - -1. **File storage system**: select **Azure Blob Storage**. The Azure-specific fields appear and the S3/local fields are hidden. -2. **Azure cloud**: select the Azure cloud that hosts the storage account: - - - **Azure Commercial** (default): the global Azure cloud (``{account}.blob.core.windows.net``). Only the storage account name is required. - - **Azure Government**: the US Government cloud (``{account}.blob.core.usgovcloudapi.net``). Only the storage account name is required. - - **Custom Endpoint**: any other Azure cloud (for example, Azure China), an Azurite emulator, or a reverse proxy. Provide the full Blob service URL via **Azure endpoint** below. - -3. **Azure Storage account**: the storage account name (for example, ``acmemattermost``). -4. **Azure container**: the container name (for example, ``mattermost``). -5. **Azure path prefix**: optional. Set this if you want Mattermost to write under a sub-path inside the container, for example ``prod/``. Leave empty to use the container root. -6. **Azure authentication**: select the mode you set up in step 1: - - - **Shared key** (default): Mattermost signs each request with the Storage Account access key. Choose this if you completed `Option A: Shared key`_. - - **Default credential (Microsoft Entra ID)**: Mattermost authenticates as the identity provided by the host environment. Choose this if you completed `Option B: Default credential (Microsoft Entra ID)`_. The **Azure Storage account key** field below is hidden because the access key is not used in this mode. - -7. **Azure Storage account key** (visible only when **Azure authentication** is **Shared key**): paste the shared key from `Option A: Shared key`_. -8. **Azure endpoint** (visible only when **Azure cloud** is set to **Custom Endpoint**): the full Blob service URL, including scheme and storage account. Mattermost passes this URL to the Azure SDK unchanged, so the storage account must already be embedded in the hostname (vhost-style, for example ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in the path (path-style, for example ``http://localhost:10000/devstoreaccount1/`` for Azurite). The chosen authentication mode signs against the host this URL points at, so the host must serve the storage account named above. -9. **Enable secure Azure Blob Storage connections** (visible only when **Azure cloud** is **Azure Commercial** or **Azure Government**): keep this enabled (the default). The Custom Endpoint cloud determines the scheme from the **Azure endpoint** URL, so this toggle is hidden for that mode. -10. **Azure request timeout (milliseconds)**: default is ``30000`` (30 seconds). Increase only if your network needs more time for large objects. - -Save the settings and click **Test Connection**. Mattermost issues a no-op write/read/delete against the configured container using the credentials submitted in the form. A green ``Connection was successful`` message confirms the credentials, container name, and endpoint all work. A red error message includes the underlying reason; common ones are listed in `Troubleshooting`_. - -.. warning:: - - **Restart required.** The Mattermost server caches the file storage backend at startup and does not re-create it when the file storage configuration changes. After saving, restart every Mattermost server in the deployment (``systemctl restart mattermost``, recycle the container, or roll the deployment in your cluster) for the new driver to take effect. **Test Connection** works before the restart because it builds a temporary backend from the submitted form values. - -.. warning:: - - Switching the file driver does **not** migrate existing files. If you are moving an existing deployment from Amazon S3, see `Migrate existing files from Amazon S3`_ below before changing the driver. For migrations from local disk, copy the directory contents into the Azure container using ``azcopy`` (`docs `__). In either case, files uploaded before the switch are unreachable once the driver changes unless they are present at the same key in the destination. - -Step 3: Verify --------------- - -1. After the restart, reload the System Console or any channel. -2. Upload an attachment in any channel. A small image is a good test, because Mattermost stores three blobs for an image (original, preview, thumbnail), which exercises the upload path more thoroughly than a plain file. -3. The post should render the attachment and preview as usual. -4. In the Azure portal, open the container and confirm new blobs appeared under the path ``/teams//channels//users///`` (the same layout the local-disk and S3 backends use). For an image you will see ``.``, ``_preview.``, and ``_thumb.``. - -Migrate existing files from Amazon S3 -------------------------------------- - -If you are switching an existing deployment from S3 to Azure Blob Storage, the file content must be present in the Azure container at the same key Mattermost would have written to. Mattermost itself does not move files between backends, so this is an out-of-band copy that you run once before flipping the driver. - -Mattermost writes blobs at the same relative path on every backend: - -.. code-block:: text - - {path-prefix}/{YYYYMMDD}/teams/{teamID}/channels/{channelID}/users/{userID}/{fileID}/{filename} - -This means a straight key-for-key copy from the S3 bucket to the Azure container is sufficient. If you use ``AmazonS3PathPrefix`` on the S3 side, set ``AzurePathPrefix`` to the same value on the Azure side (or rewrite the prefix during the copy). - -There are multiple ways to accomplish this. The recommended way is using the `Azure Storage Mover service `__, which provides a cloud-to-cloud migration from Amazon S3 to Azure Blob Storage. - -There are alternative tools that can also help, like `rclone `__ and `AzCopy `__. - -(Optional) Configure the export backend ---------------------------------------- - -Compliance and data exports can be stored separately from regular file uploads. The **File Storage (Exports)** section directly below **File Storage** in the System Console mirrors the fields above and accepts the same Azure credentials. Customers typically point exports at a different container (or a different account) so the export retention policy can differ from regular uploads. The export target is an independent backend with its own driver and credentials, so it doesn't have to use the same provider as regular uploads; e.g., you can keep uploads on Amazon S3 and send exports to Azure Blob Storage, or the reverse. - -See :ref:`Enable dedicated export filestore target ` for the full list of ``ExportAzure*`` keys. - -Troubleshooting ---------------- - -.. list-table:: - :header-rows: 1 - :widths: 35 65 - - * - Symptom - - Likely cause - * - ``AuthenticationFailed`` on **Test Connection** - - When **Azure authentication** is **Shared key**: wrong account name or shared key. Confirm both in the **Access keys** blade of the Azure portal. When **Azure authentication** is **Default credential**: no identity source was available -- the host has no managed identity, the workload-identity federation is not set up, and no ``AZURE_TENANT_ID`` / ``AZURE_CLIENT_ID`` / ``AZURE_CLIENT_SECRET`` environment variables are set. - * - ``AuthorizationPermissionMismatch`` on **Test Connection** - - Only applies when **Azure authentication** is **Default credential**. The identity the SDK selected does not hold a data-plane role on the storage account. Grant **Storage Blob Data Contributor** to that identity per `Option B: Default credential (Microsoft Entra ID)`_, then wait 30-120 seconds for the role assignment to propagate. - * - ``ContainerNotFound`` - - Container name is wrong or was created under a different storage account. - * - ``connection refused`` or TLS errors - - When **Azure cloud** is **Custom Endpoint**, the **Azure endpoint** URL points at a host that isn't reachable or uses the wrong scheme. When **Azure cloud** is **Azure Commercial** or **Azure Government**, **Enable secure Azure Blob Storage connections** is disabled in front of a TLS-only destination. - * - **Test Connection** succeeds but uploads in channels fail - - Check **System Console > Reporting > Server Logs** for the Azure error returned by the SDK. The most common cause is a forgotten server restart after **Save**. - * - Files uploaded before the switch are no longer visible - - The existing files are still on the previous backend. For S3 migrations, follow `Migrate existing files from Amazon S3`_ to copy the bucket into the Azure container at matching keys. For other backends, copy the contents into the Azure container with ``azcopy`` (or equivalent) and confirm the destination path matches the layout Mattermost uses. - -Reference ---------- - -Each Azure setting is documented in detail in :ref:`Environment configuration settings `: - -- :ref:`File storage system ` (``FileSettings.DriverName``) -- :ref:`Azure Storage account ` (``FileSettings.AzureStorageAccount``) -- :ref:`Azure container ` (``FileSettings.AzureContainer``) -- :ref:`Azure path prefix ` (``FileSettings.AzurePathPrefix``) -- :ref:`Azure authentication ` (``FileSettings.AzureAuthMode``) -- :ref:`Azure Storage account key ` (``FileSettings.AzureAccessKey``) -- :ref:`Azure cloud ` (``FileSettings.AzureCloud``) -- :ref:`Azure endpoint ` (``FileSettings.AzureEndpoint``) -- :ref:`Enable secure Azure Blob Storage connections ` (``FileSettings.AzureSSL``) -- :ref:`Azure request timeout ` (``FileSettings.AzureRequestTimeoutMilliseconds``) From ef0d13ab84a231f7a6b545f3557fa55f22cdfc40 Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:31:45 -0700 Subject: [PATCH 09/10] Update azure-blob-storage.rst --- .../configure/azure-blob-storage.rst | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/source/administration-guide/configure/azure-blob-storage.rst b/source/administration-guide/configure/azure-blob-storage.rst index 8b137891791..2a238454a3c 100644 --- a/source/administration-guide/configure/azure-blob-storage.rst +++ b/source/administration-guide/configure/azure-blob-storage.rst @@ -1 +1,217 @@ +Configure Azure Blob Storage as the Mattermost file store +========================================================== +.. include:: ../../_static/badges/all-commercial.rst + :start-after: :nosearch: + +Mattermost can store user uploads -- attachments, profile images, plugin assets, emoji, compliance exports -- in an Azure Storage account. This guide walks an administrator through the steps to provision the Azure side and point a Mattermost server at it via the System Console. + +Prerequisites +------------- + +- An Azure subscription with a storage account and a container already created. +- Either the Azure portal, or the `Azure CLI `__ (``az``) installed and signed in with ``az login``. Both are documented below. +- A Mattermost deployment (v11.9 or later) with System Console access for a System Admin account. + +If you plan to migrate existing files from another backend, take a backup of the current storage location (S3 bucket, local disk, etc.) before changing the configuration. Switching the file driver does not migrate existing files automatically. + +Step 1: Choose an authentication mode +------------------------------------- + +Mattermost supports two ways for the server to authenticate to Azure. Pick the one that fits how the server runs: + +- **Shared key**: the server signs each request with the :ref:`Storage Account access key `. Works anywhere Mattermost runs (on-premises, non-Azure cloud, local development) because it does not depend on the host having an Azure identity. The trade-off is that the key is a long-lived secret stored in ``config.json``. +- **Default credential (Microsoft Entra ID)**: the server obtains a token from Microsoft Entra ID and signs requests with it. No long-lived secret in Mattermost configuration. This is the recommended mode for deployments running on Azure, where the host environment already provides an identity (managed identity on Azure VM / App Service / AKS, workload identity for federated workloads, or a service principal). + +The Azure-side setup differs slightly between the two modes. Follow the subsection that matches your choice; you can switch modes later by changing the :ref:`Azure authentication ` setting in the System Console. + +Option A: Shared key +~~~~~~~~~~~~~~~~~~~~ + +Retrieve the Storage Account access key. + +**Azure portal** + +1. Open the storage account, then **Security + networking** > **Access keys**. +2. Select **Show** next to ``key1`` (or ``key2``) and copy the value. + +**Azure CLI** + +.. code-block:: bash + + az storage account keys list \ + --account-name acmemattermost \ + --resource-group mm-prod-files \ + --query "[0].value" -o tsv + +.. note:: + + Treat the shared key as a secret -- anyone with it has full access to the storage account (every container and all data it holds). A shared key can't be scoped to a single container, to specific operations, or to a resource group; if you need least-privilege access, use `Option B: Default credential (Microsoft Entra ID)`_ with a container-scoped **Storage Blob Data Contributor** role instead. Azure provides two keys so you can rotate without downtime: update Mattermost to ``key2``, regenerate ``key1``, then swap on the next rotation cycle. Plan a rotation cadence that matches your organisation's policy. + +Option B: Default credential (Microsoft Entra ID) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The server uses ``DefaultAzureCredential`` from the Azure SDK, which discovers a working identity at runtime in this order. The first source that returns a token is used. + +#. ``EnvironmentCredential`` -- service-principal environment variables. +#. ``WorkloadIdentityCredential`` -- federated workload identity. +#. ``ManagedIdentityCredential`` -- the platform-provided managed identity. +#. ``AzureCLICredential`` -- the signed-in ``az`` session, useful for local development. + +Whichever identity the SDK selects, **that** identity needs **Storage Blob Data Contributor** (or a custom role with the equivalent ``read/write/list/delete`` data-plane actions) on the storage account or container. Without it, ``TestConnection`` returns ``AuthorizationPermissionMismatch``. + +Pick the identity source that matches the host: + +.. list-table:: + :header-rows: 1 + :widths: 25 75 + + * - Host + - Identity source + * - Azure VM, App Service, AKS, Container Apps + - Assign a **system-assigned** or **user-assigned managed identity** to the compute resource. ``DefaultAzureCredential`` resolves to ``ManagedIdentityCredential`` with no extra configuration. For user-assigned identities, set ``AZURE_CLIENT_ID`` in the server's environment so the SDK picks the right one. + * - AKS with workload-identity federation + - Annotate the Mattermost ``ServiceAccount`` with the client ID and configure the OIDC issuer per the `AKS workload identity guide `__. ``DefaultAzureCredential`` resolves to ``WorkloadIdentityCredential``. + * - Non-Azure host or container + - Create a service principal and set ``AZURE_TENANT_ID``, ``AZURE_CLIENT_ID``, and ``AZURE_CLIENT_SECRET`` (or ``AZURE_CLIENT_CERTIFICATE_PATH``) in the server's environment. ``DefaultAzureCredential`` resolves to ``EnvironmentCredential``. + * - Local development on an admin's workstation + - Sign in with ``az login``. ``DefaultAzureCredential`` resolves to ``AzureCLICredential``. + +To prepare the account you're going to use, you'll need to assign the role from the Azure Portal or using the Azure CLI, as shown below (substitute the principal of the identity Mattermost will authenticate as): + +.. code-block:: bash + + STORAGE_ACCOUNT_ID=$(az storage account show \ + --name acmemattermost \ + --resource-group mm-prod-files \ + --query id -o tsv) + + # For a managed identity (system-assigned on a VM/App Service/AKS pod): + az role assignment create \ + --assignee-object-id "" \ + --assignee-principal-type ServicePrincipal \ + --role "Storage Blob Data Contributor" \ + --scope "$STORAGE_ACCOUNT_ID" + + # For a service principal: + az role assignment create \ + --assignee "" \ + --role "Storage Blob Data Contributor" \ + --scope "$STORAGE_ACCOUNT_ID" + +.. note:: + + Granting the role requires **User Access Administrator** or **Owner** on the storage account; ``Contributor`` is not enough. Plan to have an administrator with that role run the ``az role assignment create`` step. If you scope the role to a single container instead of the whole storage account, replace ``--scope "$STORAGE_ACCOUNT_ID"`` with ``--scope "$STORAGE_ACCOUNT_ID/blobServices/default/containers/"``. + +.. tip:: + + Azure RBAC role assignments can take 30-120 seconds to propagate. If the first ``TestConnection`` returns ``AuthorizationPermissionMismatch`` immediately after the role assignment, wait a minute and retry before assuming a misconfiguration. + +.. note:: + + Mattermost holds the credential, not the token. Microsoft Entra ID access tokens are short-lived, but the Azure SDK caches each token and refreshes it automatically before it expires, so routine token rotation never interrupts file access while the server is running. Access stops only if the underlying identity or its authorization changes or is removed. + +Step 2: Configure Mattermost +---------------------------- + +Sign in as a System Admin and open **System Console > Environment > File Storage**. + +1. **File storage system**: select **Azure Blob Storage**. The Azure-specific fields appear and the S3/local fields are hidden. +2. **Azure cloud**: select the Azure cloud that hosts the storage account: + + - **Azure Commercial** (default): the global Azure cloud (``{account}.blob.core.windows.net``). Only the storage account name is required. + - **Azure Government**: the US Government cloud (``{account}.blob.core.usgovcloudapi.net``). Only the storage account name is required. + - **Custom Endpoint**: any other Azure cloud (for example, Azure China), an Azurite emulator, or a reverse proxy. Provide the full Blob service URL via **Azure endpoint** below. + +3. **Azure Storage account**: the storage account name (for example, ``acmemattermost``). +4. **Azure container**: the container name (for example, ``mattermost``). +5. **Azure path prefix**: optional. Set this if you want Mattermost to write under a sub-path inside the container, for example ``prod/``. Leave empty to use the container root. +6. **Azure authentication**: select the mode you set up in step 1: + + - **Shared key** (default): Mattermost signs each request with the Storage Account access key. Choose this if you completed `Option A: Shared key`_. + - **Default credential (Microsoft Entra ID)**: Mattermost authenticates as the identity provided by the host environment. Choose this if you completed `Option B: Default credential (Microsoft Entra ID)`_. The **Azure Storage account key** field below is hidden because the access key is not used in this mode. + +7. **Azure Storage account key** (visible only when **Azure authentication** is **Shared key**): paste the shared key from `Option A: Shared key`_. +8. **Azure endpoint** (visible only when **Azure cloud** is set to **Custom Endpoint**): the full Blob service URL, including scheme and storage account. Mattermost passes this URL to the Azure SDK unchanged, so the storage account must already be embedded in the hostname (vhost-style, for example ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in the path (path-style, for example ``http://localhost:10000/devstoreaccount1/`` for Azurite). The chosen authentication mode signs against the host this URL points at, so the host must serve the storage account named above. +9. **Enable secure Azure Blob Storage connections** (visible only when **Azure cloud** is **Azure Commercial** or **Azure Government**): keep this enabled (the default). The Custom Endpoint cloud determines the scheme from the **Azure endpoint** URL, so this toggle is hidden for that mode. +10. **Azure request timeout (milliseconds)**: default is ``30000`` (30 seconds). Increase only if your network needs more time for large objects. + +Save the settings and click **Test Connection**. Mattermost issues a no-op write/read/delete against the configured container using the credentials submitted in the form. A green ``Connection was successful`` message confirms the credentials, container name, and endpoint all work. A red error message includes the underlying reason; common ones are listed in `Troubleshooting`_. + +.. warning:: + + **Restart required.** The Mattermost server caches the file storage backend at startup and does not re-create it when the file storage configuration changes. After saving, restart every Mattermost server in the deployment (``systemctl restart mattermost``, recycle the container, or roll the deployment in your cluster) for the new driver to take effect. **Test Connection** works before the restart because it builds a temporary backend from the submitted form values. + +.. warning:: + + Switching the file driver does **not** migrate existing files. If you are moving an existing deployment from Amazon S3, see `Migrate existing files from Amazon S3`_ below before changing the driver. For migrations from local disk, copy the directory contents into the Azure container using ``azcopy`` (`docs `__). In either case, files uploaded before the switch are unreachable once the driver changes unless they are present at the same key in the destination. + +Step 3: Verify +-------------- + +1. After the restart, reload the System Console or any channel. +2. Upload an attachment in any channel. A small image is a good test, because Mattermost stores three blobs for an image (original, preview, thumbnail), which exercises the upload path more thoroughly than a plain file. +3. The post should render the attachment and preview as usual. +4. In the Azure portal, open the container and confirm new blobs appeared under the path ``/teams//channels//users///`` (the same layout the local-disk and S3 backends use). For an image you will see ``.``, ``_preview.``, and ``_thumb.``. + +Migrate existing files from Amazon S3 +------------------------------------- + +If you are switching an existing deployment from S3 to Azure Blob Storage, the file content must be present in the Azure container at the same key Mattermost would have written to. Mattermost itself does not move files between backends, so this is an out-of-band copy that you run once before flipping the driver. + +Mattermost writes blobs at the same relative path on every backend: + +.. code-block:: text + + {path-prefix}/{YYYYMMDD}/teams/{teamID}/channels/{channelID}/users/{userID}/{fileID}/{filename} + +This means a straight key-for-key copy from the S3 bucket to the Azure container is sufficient. If you use ``AmazonS3PathPrefix`` on the S3 side, set ``AzurePathPrefix`` to the same value on the Azure side (or rewrite the prefix during the copy). + +There are multiple ways to accomplish this. The recommended way is using the `Azure Storage Mover service `__, which provides a cloud-to-cloud migration from Amazon S3 to Azure Blob Storage. + +There are alternative tools that can also help, like `rclone `__ and `AzCopy `__. + +(Optional) Configure the export backend +--------------------------------------- + +Compliance and data exports can be stored separately from regular file uploads. The **File Storage (Exports)** section directly below **File Storage** in the System Console mirrors the fields above and accepts the same Azure credentials. Customers typically point exports at a different container (or a different account) so the export retention policy can differ from regular uploads. The export target is an independent backend with its own driver and credentials, so it doesn't have to use the same provider as regular uploads; e.g., you can keep uploads on Amazon S3 and send exports to Azure Blob Storage, or the reverse. + +See :ref:`Enable dedicated export filestore target ` for the full list of ``ExportAzure*`` keys. + +Troubleshooting +--------------- + +.. list-table:: + :header-rows: 1 + :widths: 35 65 + + * - Symptom + - Likely cause + * - ``AuthenticationFailed`` on **Test Connection** + - When **Azure authentication** is **Shared key**: wrong account name or shared key. Confirm both in the **Access keys** blade of the Azure portal. When **Azure authentication** is **Default credential**: no identity source was available -- the host has no managed identity, the workload-identity federation is not set up, and no ``AZURE_TENANT_ID`` / ``AZURE_CLIENT_ID`` / ``AZURE_CLIENT_SECRET`` environment variables are set. + * - ``AuthorizationPermissionMismatch`` on **Test Connection** + - Only applies when **Azure authentication** is **Default credential**. The identity the SDK selected does not hold a data-plane role on the storage account. Grant **Storage Blob Data Contributor** to that identity per `Option B: Default credential (Microsoft Entra ID)`_, then wait 30-120 seconds for the role assignment to propagate. + * - ``ContainerNotFound`` + - Container name is wrong or was created under a different storage account. + * - ``connection refused`` or TLS errors + - When **Azure cloud** is **Custom Endpoint**, the **Azure endpoint** URL points at a host that isn't reachable or uses the wrong scheme. When **Azure cloud** is **Azure Commercial** or **Azure Government**, **Enable secure Azure Blob Storage connections** is disabled in front of a TLS-only destination. + * - **Test Connection** succeeds but uploads in channels fail + - Check **System Console > Reporting > Server Logs** for the Azure error returned by the SDK. The most common cause is a forgotten server restart after **Save**. + * - Files uploaded before the switch are no longer visible + - The existing files are still on the previous backend. For S3 migrations, follow `Migrate existing files from Amazon S3`_ to copy the bucket into the Azure container at matching keys. For other backends, copy the contents into the Azure container with ``azcopy`` (or equivalent) and confirm the destination path matches the layout Mattermost uses. + +Reference +--------- + +Each Azure setting is documented in detail in :ref:`Environment configuration settings `: + +- :ref:`File storage system ` (``FileSettings.DriverName``) +- :ref:`Azure Storage account ` (``FileSettings.AzureStorageAccount``) +- :ref:`Azure container ` (``FileSettings.AzureContainer``) +- :ref:`Azure path prefix ` (``FileSettings.AzurePathPrefix``) +- :ref:`Azure authentication ` (``FileSettings.AzureAuthMode``) +- :ref:`Azure Storage account key ` (``FileSettings.AzureAccessKey``) +- :ref:`Azure cloud ` (``FileSettings.AzureCloud``) +- :ref:`Azure endpoint ` (``FileSettings.AzureEndpoint``) +- :ref:`Enable secure Azure Blob Storage connections ` (``FileSettings.AzureSSL``) +- :ref:`Azure request timeout ` (``FileSettings.AzureRequestTimeoutMilliseconds``) From 7aceaf316c27421249eceb87e5a6c33f1ac3f23f Mon Sep 17 00:00:00 2001 From: Combs7th <147677911+Combs7th@users.noreply.github.com> Date: Fri, 12 Jun 2026 17:00:28 -0700 Subject: [PATCH 10/10] Remove unintended configure file changes --- .../authentication-configuration-settings.rst | 2 +- .../configure/azure-blob-storage.rst | 217 ----------------- .../environment-configuration-settings.rst | 224 +----------------- 3 files changed, 5 insertions(+), 438 deletions(-) delete mode 100644 source/administration-guide/configure/azure-blob-storage.rst diff --git a/source/administration-guide/configure/authentication-configuration-settings.rst b/source/administration-guide/configure/authentication-configuration-settings.rst index d5c08d6fd0b..f9e68d6b7cf 100644 --- a/source/administration-guide/configure/authentication-configuration-settings.rst +++ b/source/administration-guide/configure/authentication-configuration-settings.rst @@ -2708,4 +2708,4 @@ Enable guest magic link authentication +-------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------+ .. note:: - See the :ref:`guest accounts ` documentation for guest user setup details. + See the :ref:`guest accounts ` documentation for guest user setup details. \ No newline at end of file diff --git a/source/administration-guide/configure/azure-blob-storage.rst b/source/administration-guide/configure/azure-blob-storage.rst deleted file mode 100644 index 2a238454a3c..00000000000 --- a/source/administration-guide/configure/azure-blob-storage.rst +++ /dev/null @@ -1,217 +0,0 @@ -Configure Azure Blob Storage as the Mattermost file store -========================================================== - -.. include:: ../../_static/badges/all-commercial.rst - :start-after: :nosearch: - -Mattermost can store user uploads -- attachments, profile images, plugin assets, emoji, compliance exports -- in an Azure Storage account. This guide walks an administrator through the steps to provision the Azure side and point a Mattermost server at it via the System Console. - -Prerequisites -------------- - -- An Azure subscription with a storage account and a container already created. -- Either the Azure portal, or the `Azure CLI `__ (``az``) installed and signed in with ``az login``. Both are documented below. -- A Mattermost deployment (v11.9 or later) with System Console access for a System Admin account. - -If you plan to migrate existing files from another backend, take a backup of the current storage location (S3 bucket, local disk, etc.) before changing the configuration. Switching the file driver does not migrate existing files automatically. - -Step 1: Choose an authentication mode -------------------------------------- - -Mattermost supports two ways for the server to authenticate to Azure. Pick the one that fits how the server runs: - -- **Shared key**: the server signs each request with the :ref:`Storage Account access key `. Works anywhere Mattermost runs (on-premises, non-Azure cloud, local development) because it does not depend on the host having an Azure identity. The trade-off is that the key is a long-lived secret stored in ``config.json``. -- **Default credential (Microsoft Entra ID)**: the server obtains a token from Microsoft Entra ID and signs requests with it. No long-lived secret in Mattermost configuration. This is the recommended mode for deployments running on Azure, where the host environment already provides an identity (managed identity on Azure VM / App Service / AKS, workload identity for federated workloads, or a service principal). - -The Azure-side setup differs slightly between the two modes. Follow the subsection that matches your choice; you can switch modes later by changing the :ref:`Azure authentication ` setting in the System Console. - -Option A: Shared key -~~~~~~~~~~~~~~~~~~~~ - -Retrieve the Storage Account access key. - -**Azure portal** - -1. Open the storage account, then **Security + networking** > **Access keys**. -2. Select **Show** next to ``key1`` (or ``key2``) and copy the value. - -**Azure CLI** - -.. code-block:: bash - - az storage account keys list \ - --account-name acmemattermost \ - --resource-group mm-prod-files \ - --query "[0].value" -o tsv - -.. note:: - - Treat the shared key as a secret -- anyone with it has full access to the storage account (every container and all data it holds). A shared key can't be scoped to a single container, to specific operations, or to a resource group; if you need least-privilege access, use `Option B: Default credential (Microsoft Entra ID)`_ with a container-scoped **Storage Blob Data Contributor** role instead. Azure provides two keys so you can rotate without downtime: update Mattermost to ``key2``, regenerate ``key1``, then swap on the next rotation cycle. Plan a rotation cadence that matches your organisation's policy. - -Option B: Default credential (Microsoft Entra ID) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The server uses ``DefaultAzureCredential`` from the Azure SDK, which discovers a working identity at runtime in this order. The first source that returns a token is used. - -#. ``EnvironmentCredential`` -- service-principal environment variables. -#. ``WorkloadIdentityCredential`` -- federated workload identity. -#. ``ManagedIdentityCredential`` -- the platform-provided managed identity. -#. ``AzureCLICredential`` -- the signed-in ``az`` session, useful for local development. - -Whichever identity the SDK selects, **that** identity needs **Storage Blob Data Contributor** (or a custom role with the equivalent ``read/write/list/delete`` data-plane actions) on the storage account or container. Without it, ``TestConnection`` returns ``AuthorizationPermissionMismatch``. - -Pick the identity source that matches the host: - -.. list-table:: - :header-rows: 1 - :widths: 25 75 - - * - Host - - Identity source - * - Azure VM, App Service, AKS, Container Apps - - Assign a **system-assigned** or **user-assigned managed identity** to the compute resource. ``DefaultAzureCredential`` resolves to ``ManagedIdentityCredential`` with no extra configuration. For user-assigned identities, set ``AZURE_CLIENT_ID`` in the server's environment so the SDK picks the right one. - * - AKS with workload-identity federation - - Annotate the Mattermost ``ServiceAccount`` with the client ID and configure the OIDC issuer per the `AKS workload identity guide `__. ``DefaultAzureCredential`` resolves to ``WorkloadIdentityCredential``. - * - Non-Azure host or container - - Create a service principal and set ``AZURE_TENANT_ID``, ``AZURE_CLIENT_ID``, and ``AZURE_CLIENT_SECRET`` (or ``AZURE_CLIENT_CERTIFICATE_PATH``) in the server's environment. ``DefaultAzureCredential`` resolves to ``EnvironmentCredential``. - * - Local development on an admin's workstation - - Sign in with ``az login``. ``DefaultAzureCredential`` resolves to ``AzureCLICredential``. - -To prepare the account you're going to use, you'll need to assign the role from the Azure Portal or using the Azure CLI, as shown below (substitute the principal of the identity Mattermost will authenticate as): - -.. code-block:: bash - - STORAGE_ACCOUNT_ID=$(az storage account show \ - --name acmemattermost \ - --resource-group mm-prod-files \ - --query id -o tsv) - - # For a managed identity (system-assigned on a VM/App Service/AKS pod): - az role assignment create \ - --assignee-object-id "" \ - --assignee-principal-type ServicePrincipal \ - --role "Storage Blob Data Contributor" \ - --scope "$STORAGE_ACCOUNT_ID" - - # For a service principal: - az role assignment create \ - --assignee "" \ - --role "Storage Blob Data Contributor" \ - --scope "$STORAGE_ACCOUNT_ID" - -.. note:: - - Granting the role requires **User Access Administrator** or **Owner** on the storage account; ``Contributor`` is not enough. Plan to have an administrator with that role run the ``az role assignment create`` step. If you scope the role to a single container instead of the whole storage account, replace ``--scope "$STORAGE_ACCOUNT_ID"`` with ``--scope "$STORAGE_ACCOUNT_ID/blobServices/default/containers/"``. - -.. tip:: - - Azure RBAC role assignments can take 30-120 seconds to propagate. If the first ``TestConnection`` returns ``AuthorizationPermissionMismatch`` immediately after the role assignment, wait a minute and retry before assuming a misconfiguration. - -.. note:: - - Mattermost holds the credential, not the token. Microsoft Entra ID access tokens are short-lived, but the Azure SDK caches each token and refreshes it automatically before it expires, so routine token rotation never interrupts file access while the server is running. Access stops only if the underlying identity or its authorization changes or is removed. - -Step 2: Configure Mattermost ----------------------------- - -Sign in as a System Admin and open **System Console > Environment > File Storage**. - -1. **File storage system**: select **Azure Blob Storage**. The Azure-specific fields appear and the S3/local fields are hidden. -2. **Azure cloud**: select the Azure cloud that hosts the storage account: - - - **Azure Commercial** (default): the global Azure cloud (``{account}.blob.core.windows.net``). Only the storage account name is required. - - **Azure Government**: the US Government cloud (``{account}.blob.core.usgovcloudapi.net``). Only the storage account name is required. - - **Custom Endpoint**: any other Azure cloud (for example, Azure China), an Azurite emulator, or a reverse proxy. Provide the full Blob service URL via **Azure endpoint** below. - -3. **Azure Storage account**: the storage account name (for example, ``acmemattermost``). -4. **Azure container**: the container name (for example, ``mattermost``). -5. **Azure path prefix**: optional. Set this if you want Mattermost to write under a sub-path inside the container, for example ``prod/``. Leave empty to use the container root. -6. **Azure authentication**: select the mode you set up in step 1: - - - **Shared key** (default): Mattermost signs each request with the Storage Account access key. Choose this if you completed `Option A: Shared key`_. - - **Default credential (Microsoft Entra ID)**: Mattermost authenticates as the identity provided by the host environment. Choose this if you completed `Option B: Default credential (Microsoft Entra ID)`_. The **Azure Storage account key** field below is hidden because the access key is not used in this mode. - -7. **Azure Storage account key** (visible only when **Azure authentication** is **Shared key**): paste the shared key from `Option A: Shared key`_. -8. **Azure endpoint** (visible only when **Azure cloud** is set to **Custom Endpoint**): the full Blob service URL, including scheme and storage account. Mattermost passes this URL to the Azure SDK unchanged, so the storage account must already be embedded in the hostname (vhost-style, for example ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in the path (path-style, for example ``http://localhost:10000/devstoreaccount1/`` for Azurite). The chosen authentication mode signs against the host this URL points at, so the host must serve the storage account named above. -9. **Enable secure Azure Blob Storage connections** (visible only when **Azure cloud** is **Azure Commercial** or **Azure Government**): keep this enabled (the default). The Custom Endpoint cloud determines the scheme from the **Azure endpoint** URL, so this toggle is hidden for that mode. -10. **Azure request timeout (milliseconds)**: default is ``30000`` (30 seconds). Increase only if your network needs more time for large objects. - -Save the settings and click **Test Connection**. Mattermost issues a no-op write/read/delete against the configured container using the credentials submitted in the form. A green ``Connection was successful`` message confirms the credentials, container name, and endpoint all work. A red error message includes the underlying reason; common ones are listed in `Troubleshooting`_. - -.. warning:: - - **Restart required.** The Mattermost server caches the file storage backend at startup and does not re-create it when the file storage configuration changes. After saving, restart every Mattermost server in the deployment (``systemctl restart mattermost``, recycle the container, or roll the deployment in your cluster) for the new driver to take effect. **Test Connection** works before the restart because it builds a temporary backend from the submitted form values. - -.. warning:: - - Switching the file driver does **not** migrate existing files. If you are moving an existing deployment from Amazon S3, see `Migrate existing files from Amazon S3`_ below before changing the driver. For migrations from local disk, copy the directory contents into the Azure container using ``azcopy`` (`docs `__). In either case, files uploaded before the switch are unreachable once the driver changes unless they are present at the same key in the destination. - -Step 3: Verify --------------- - -1. After the restart, reload the System Console or any channel. -2. Upload an attachment in any channel. A small image is a good test, because Mattermost stores three blobs for an image (original, preview, thumbnail), which exercises the upload path more thoroughly than a plain file. -3. The post should render the attachment and preview as usual. -4. In the Azure portal, open the container and confirm new blobs appeared under the path ``/teams//channels//users///`` (the same layout the local-disk and S3 backends use). For an image you will see ``.``, ``_preview.``, and ``_thumb.``. - -Migrate existing files from Amazon S3 -------------------------------------- - -If you are switching an existing deployment from S3 to Azure Blob Storage, the file content must be present in the Azure container at the same key Mattermost would have written to. Mattermost itself does not move files between backends, so this is an out-of-band copy that you run once before flipping the driver. - -Mattermost writes blobs at the same relative path on every backend: - -.. code-block:: text - - {path-prefix}/{YYYYMMDD}/teams/{teamID}/channels/{channelID}/users/{userID}/{fileID}/{filename} - -This means a straight key-for-key copy from the S3 bucket to the Azure container is sufficient. If you use ``AmazonS3PathPrefix`` on the S3 side, set ``AzurePathPrefix`` to the same value on the Azure side (or rewrite the prefix during the copy). - -There are multiple ways to accomplish this. The recommended way is using the `Azure Storage Mover service `__, which provides a cloud-to-cloud migration from Amazon S3 to Azure Blob Storage. - -There are alternative tools that can also help, like `rclone `__ and `AzCopy `__. - -(Optional) Configure the export backend ---------------------------------------- - -Compliance and data exports can be stored separately from regular file uploads. The **File Storage (Exports)** section directly below **File Storage** in the System Console mirrors the fields above and accepts the same Azure credentials. Customers typically point exports at a different container (or a different account) so the export retention policy can differ from regular uploads. The export target is an independent backend with its own driver and credentials, so it doesn't have to use the same provider as regular uploads; e.g., you can keep uploads on Amazon S3 and send exports to Azure Blob Storage, or the reverse. - -See :ref:`Enable dedicated export filestore target ` for the full list of ``ExportAzure*`` keys. - -Troubleshooting ---------------- - -.. list-table:: - :header-rows: 1 - :widths: 35 65 - - * - Symptom - - Likely cause - * - ``AuthenticationFailed`` on **Test Connection** - - When **Azure authentication** is **Shared key**: wrong account name or shared key. Confirm both in the **Access keys** blade of the Azure portal. When **Azure authentication** is **Default credential**: no identity source was available -- the host has no managed identity, the workload-identity federation is not set up, and no ``AZURE_TENANT_ID`` / ``AZURE_CLIENT_ID`` / ``AZURE_CLIENT_SECRET`` environment variables are set. - * - ``AuthorizationPermissionMismatch`` on **Test Connection** - - Only applies when **Azure authentication** is **Default credential**. The identity the SDK selected does not hold a data-plane role on the storage account. Grant **Storage Blob Data Contributor** to that identity per `Option B: Default credential (Microsoft Entra ID)`_, then wait 30-120 seconds for the role assignment to propagate. - * - ``ContainerNotFound`` - - Container name is wrong or was created under a different storage account. - * - ``connection refused`` or TLS errors - - When **Azure cloud** is **Custom Endpoint**, the **Azure endpoint** URL points at a host that isn't reachable or uses the wrong scheme. When **Azure cloud** is **Azure Commercial** or **Azure Government**, **Enable secure Azure Blob Storage connections** is disabled in front of a TLS-only destination. - * - **Test Connection** succeeds but uploads in channels fail - - Check **System Console > Reporting > Server Logs** for the Azure error returned by the SDK. The most common cause is a forgotten server restart after **Save**. - * - Files uploaded before the switch are no longer visible - - The existing files are still on the previous backend. For S3 migrations, follow `Migrate existing files from Amazon S3`_ to copy the bucket into the Azure container at matching keys. For other backends, copy the contents into the Azure container with ``azcopy`` (or equivalent) and confirm the destination path matches the layout Mattermost uses. - -Reference ---------- - -Each Azure setting is documented in detail in :ref:`Environment configuration settings `: - -- :ref:`File storage system ` (``FileSettings.DriverName``) -- :ref:`Azure Storage account ` (``FileSettings.AzureStorageAccount``) -- :ref:`Azure container ` (``FileSettings.AzureContainer``) -- :ref:`Azure path prefix ` (``FileSettings.AzurePathPrefix``) -- :ref:`Azure authentication ` (``FileSettings.AzureAuthMode``) -- :ref:`Azure Storage account key ` (``FileSettings.AzureAccessKey``) -- :ref:`Azure cloud ` (``FileSettings.AzureCloud``) -- :ref:`Azure endpoint ` (``FileSettings.AzureEndpoint``) -- :ref:`Enable secure Azure Blob Storage connections ` (``FileSettings.AzureSSL``) -- :ref:`Azure request timeout ` (``FileSettings.AzureRequestTimeoutMilliseconds``) diff --git a/source/administration-guide/configure/environment-configuration-settings.rst b/source/administration-guide/configure/environment-configuration-settings.rst index 5db975b32fa..e3a47df768d 100644 --- a/source/administration-guide/configure/environment-configuration-settings.rst +++ b/source/administration-guide/configure/environment-configuration-settings.rst @@ -2000,11 +2000,7 @@ With self-hosted deployments, you can configure file storage settings by going t .. note:: - Mattermost supports storing files on the local filesystem, Amazon S3 or S3-compatible containers, and Azure Blob Storage. We have tested Mattermost with `Digital Ocean Spaces `__, but not all S3-compatible containers on the market. If you are looking to use other S3-compatible containers, we recommend completing your own testing. You can also use local storage or a network drive using NFS. - -.. seealso:: - - For a step-by-step walk-through covering Azure resource provisioning, System Console configuration, and verification, see :doc:`Configure Azure Blob Storage as the Mattermost file store `. + Mattermost currently supports storing files on the local filesystem and Amazon S3 or S3-compatible containers. We have tested Mattermost with `Digital Ocean Spaces `__, but not all S3-compatible containers on the market. If you are looking to use other S3-compatible containers, we recommend completing your own testing. You can also use local storage or a network drive using NFS. .. config:setting:: file-storage-system :displayname: File storage system (File Storage) @@ -2015,14 +2011,13 @@ With self-hosted deployments, you can configure file storage settings by going t - **local**: **(Default)** Files and images are stored in the specified local file directory. - **amazons3**: Files and images are stored on Amazon S3 based on the access key, bucket, and region fields provided. - - **azureblob**: Files and images are stored on Azure Blob Storage based on the storage account, key, and container fields provided. File storage system ~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------------------+-----------------------------------------------------------------------------+ | The type of file storage system used. | - System Config path: **Environment > File Storage** | -| Can be Local File System, Amazon S3, or Azure Blob Storage. | - ``config.json`` setting: ``FileSettings`` > ``DriverName`` > ``"local"`` | +| Can be either Local File System or Amazon S3. | - ``config.json`` setting: ``FileSettings`` > ``DriverName`` > ``"local"`` | | | - Environment variable: ``MM_FILESETTINGS_DRIVERNAME`` | | - **local**: **(Default)** Files and images are stored in | | | the specified local file directory. | | @@ -2030,15 +2025,8 @@ File storage system | based on the access key, bucket, and region fields | | | provided. The driver is compatible with other S3-compatible | | | services, such as Digital Ocean Spaces. | | -| - **azureblob**: Files and images are stored on Azure Blob | | -| Storage based on the storage account name, shared key, and | | -| container fields provided. | | +---------------------------------------------------------------+-----------------------------------------------------------------------------+ -.. note:: - - After saving a new file storage system, restart every Mattermost server in the deployment for the change to take effect. The file storage backend is initialized at startup and isn't rebuilt automatically when ``FileSettings`` change at runtime. - .. config:setting:: local-storage-directory :displayname: Local storage directory (File Storage) :systemconsole: Environment > File Storage @@ -2486,200 +2474,6 @@ Amazon S3 request timeout | Default is 30000 (30 seconds). | | +---------------------------------------------------------------+--------------------------------------------------------------------------------------------------+ -.. config:setting:: azure-storage-account - :displayname: Azure Storage account (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureStorageAccount - :environment: MM_FILESETTINGS_AZURESTORAGEACCOUNT - :description: The name of your Azure Storage account. - -Azure Storage account -~~~~~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| The name of your Azure Storage account. | - System Config path: **Environment > File Storage** | -| | - ``config.json`` setting: ``FileSettings`` > ``AzureStorageAccount`` | -| A string with the storage account name as it appears in the | - Environment variable: ``MM_FILESETTINGS_AZURESTORAGEACCOUNT`` | -| Azure portal. Must be 3-24 lowercase letters and numbers. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-container - :displayname: Azure container (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureContainer - :environment: MM_FILESETTINGS_AZURECONTAINER - :description: The name of the container in your Azure Storage account. - -Azure container -~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| The name of the container in your Azure Storage account | - System Config path: **Environment > File Storage** | -| where Mattermost stores uploads. | - ``config.json`` setting: ``FileSettings`` > ``AzureContainer`` | -| | - Environment variable: ``MM_FILESETTINGS_AZURECONTAINER`` | -| A string with the container name. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-path-prefix - :displayname: Azure path prefix (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzurePathPrefix - :environment: MM_FILESETTINGS_AZUREPATHPREFIX - :description: An optional path prefix to use for blobs in your Azure container. Leave empty to write at the container root. - -Azure path prefix -~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| An optional path prefix to use for blobs in your Azure | - System Config path: **Environment > File Storage** | -| container. | - ``config.json`` setting: ``FileSettings`` > ``AzurePathPrefix`` | -| | - Environment variable: ``MM_FILESETTINGS_AZUREPATHPREFIX`` | -| A string containing the path prefix. Leave empty to write at | | -| the container root. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-authentication - :displayname: Azure authentication (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureAuthMode - :environment: MM_FILESETTINGS_AZUREAUTHMODE - :description: Selects how Mattermost authenticates to Azure. One of ``shared_key`` (default) or ``default_credential``. - -Azure authentication -~~~~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| Selects how Mattermost authenticates to the Azure Storage | - System Config path: **Environment > File Storage** | -| account. | - ``config.json`` setting: ``FileSettings`` > ``AzureAuthMode`` | -| | - Environment variable: ``MM_FILESETTINGS_AZUREAUTHMODE`` | -| - ``shared_key``: **(Default)** Mattermost signs requests | | -| with the Storage Account access key in | | -| ``FileSettings.AzureAccessKey``. Works for any deployment | | -| (on-premises, non-Azure cloud, local development). | | -| - ``default_credential``: Mattermost obtains an Entra ID | | -| token via the Azure SDK's ``DefaultAzureCredential`` chain | | -| (managed identity, workload identity, service-principal | | -| environment variables, or ``az login`` -- in that order) | | -| and signs requests with it. ``FileSettings.AzureAccessKey`` | | -| is ignored. Recommended for deployments on Azure where the | | -| host already provides a managed identity. | | -| | | -| The identity the SDK selects must hold **Storage Blob | | -| Data Contributor** (or equivalent) on the storage account | | -| or container. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-storage-account-key - :displayname: Azure Storage account key (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureAccessKey - :environment: MM_FILESETTINGS_AZUREACCESSKEY - :description: The shared key for your Azure Storage account. Used only when ``FileSettings.AzureAuthMode`` is ``shared_key``. - -Azure Storage account key -~~~~~~~~~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| The shared key for your Azure Storage account. Used only | - System Config path: **Environment > File Storage** | -| when ``FileSettings.AzureAuthMode`` is ``shared_key``. | - ``config.json`` setting: ``FileSettings`` > ``AzureAccessKey`` | -| Find this value in the Azure portal under your storage | - Environment variable: ``MM_FILESETTINGS_AZUREACCESSKEY`` | -| account's **Security + networking > Access keys** blade. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. note:: - - Treat the shared key as a secret. Azure provides two keys to support rotation without downtime: update Mattermost to one key, regenerate the other, then swap on the next rotation cycle. - -.. config:setting:: azure-cloud - :displayname: Azure cloud (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureCloud - :environment: MM_FILESETTINGS_AZURECLOUD - :description: Selects which Azure cloud hosts the storage account. One of ``commercial`` (default), ``government``, or ``custom``. - -Azure cloud -~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| Selects which Azure cloud Mattermost connects to. The choice | - System Config path: **Environment > File Storage** | -| determines which host the Azure SDK signs requests against. | - ``config.json`` setting: ``FileSettings`` > ``AzureCloud`` | -| | - Environment variable: ``MM_FILESETTINGS_AZURECLOUD`` | -| - ``commercial``: **(Default)** Vhost-style against | | -| ``{account}.blob.core.windows.net``. Only the storage | | -| account name is required. | | -| - ``government``: Vhost-style against | | -| ``{account}.blob.core.usgovcloudapi.net`` (Azure | | -| Government). Only the storage account name is required. | | -| - ``custom``: Mattermost uses the value of | | -| ``FileSettings.AzureEndpoint`` as the full Blob service | | -| URL. Use this for Azurite, reverse proxies, Azure China, or | | -| any other Azure cloud that doesn't have a built-in preset. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-endpoint - :displayname: Azure endpoint (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureEndpoint - :environment: MM_FILESETTINGS_AZUREENDPOINT - :description: Full Blob service URL used when ``FileSettings.AzureCloud`` is ``custom``. Ignored for the ``commercial`` and ``government`` clouds. - -Azure endpoint -~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| Full Blob service URL, including scheme and storage account. | - System Config path: **Environment > File Storage** | -| Used only when ``FileSettings.AzureCloud`` is ``custom``; | - ``config.json`` setting: ``FileSettings`` > ``AzureEndpoint`` | -| ignored for the ``commercial`` and ``government`` clouds | - Environment variable: ``MM_FILESETTINGS_AZUREENDPOINT`` | -| (which derive the URL from the storage account name). | | -| | | -| Mattermost passes this URL to the Azure SDK unchanged, so | | -| the storage account must already be embedded in the hostname | | -| (vhost-style, for example | | -| ``https://acmemattermost.blob.core.chinacloudapi.cn/``) or in | | -| the path (path-style, for example | | -| ``http://localhost:10000/devstoreaccount1/`` for Azurite). | | -| Shared-key auth signs against the host this URL points at, so | | -| make sure it actually serves the storage account configured | | -| in ``FileSettings.AzureStorageAccount``. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: enable-secure-azure-blob-storage-connections - :displayname: Enable secure Azure Blob Storage connections (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureSSL - :environment: MM_FILESETTINGS_AZURESSL - :description: Enable or disable secure Azure Blob Storage connections. Default value is **true**. - -Enable secure Azure Blob Storage connections -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+--------------------------------------------------------------------------+ -| Enable or disable secure connections to Azure Blob Storage. | - System Config path: **Environment > File Storage** | -| | - ``config.json`` setting: ``FileSettings`` > ``AzureSSL`` > ``true`` | -| - **true**: **(Default)** Enables only secure Azure Blob | - Environment variable: ``MM_FILESETTINGS_AZURESSL`` | -| Storage connections. | | -| - **false**: Allows insecure connections. Only set to | | -| **false** when pointing at a local emulator without TLS. | | -+---------------------------------------------------------------+--------------------------------------------------------------------------+ - -.. config:setting:: azure-request-timeout - :displayname: Azure request timeout (File Storage) - :systemconsole: Environment > File Storage - :configjson: .FileSettings.AzureRequestTimeoutMilliseconds - :environment: MM_FILESETTINGS_AZUREREQUESTTIMEOUTMILLISECONDS - :description: Amount of time, in milliseconds, before requests to Azure Blob Storage time out. Default value is 30000 (30 seconds). - -Azure request timeout -~~~~~~~~~~~~~~~~~~~~~ - -+---------------------------------------------------------------+-----------------------------------------------------------------------------------------------+ -| The amount of time, in milliseconds, before requests to | - System Config path: **Environment > File Storage** | -| Azure Blob Storage time out. | - ``config.json`` setting: ``FileSettings`` > ``AzureRequestTimeoutMilliseconds`` > ``30000`` | -| | - Environment variable: ``MM_FILESETTINGS_AZUREREQUESTTIMEOUTMILLISECONDS`` | -| Default is 30000 (30 seconds). Increase only if your network | | -| needs more time for large objects. | | -+---------------------------------------------------------------+-----------------------------------------------------------------------------------------------+ - .. config:setting:: initial-font :displayname: Initial font (File Storage) :systemconsole: N/A @@ -4994,16 +4788,6 @@ Enable dedicated export filestore target | - ``ExportAmazonS3Trace`` | | | - ``ExportAmazonS3RequestTimeoutMilliseconds`` | | | - ``ExportAmazonS3PresignExpiresSeconds`` | | -| - ``ExportAzureStorageAccount`` | | -| - ``ExportAzureAuthMode`` | | -| - ``ExportAzureAccessKey`` | | -| - ``ExportAzureContainer`` | | -| - ``ExportAzurePathPrefix`` | | -| - ``ExportAzureCloud`` | | -| - ``ExportAzureEndpoint`` | | -| - ``ExportAzureSSL`` | | -| - ``ExportAzureRequestTimeoutMilliseconds`` | | -| - ``ExportAzurePresignExpiresSeconds`` | | | | | | - **False**: (**Default**) Standard | | | :ref:`file storage | | @@ -5014,5 +4798,5 @@ Enable dedicated export filestore target .. note:: - - When an alternate filestore target is configured, Mattermost Cloud admins can generate a presigned download URL for exports using the ``/exportlink [job-id|zip file|latest]`` slash command. On Amazon S3 this is an S3 presigned URL; on Azure Blob Storage it's a Shared Access Signature (SAS) URL. The lifetimes of these URLs are controlled, respectively, by ``ExportAmazonS3PresignExpiresSeconds`` or ``ExportAzurePresignExpiresSeconds``. See the :ref:`Mattermost data migration ` documentation for details. Alternatively, Cloud and self-hosted admins can use the :ref:`mmctl export generate-presigned-url ` command to generate a presigned URL directly from mmctl. - - Generating a presigned URL requires the feature flag ``EnableExportDirectDownload`` to be set to ``true``, the storage must support presigned links (Amazon S3 or Azure Blob Storage), and this experimental configuration setting must be set to ``true``. Presigned URLs for exports aren't supported for systems with shared storage. + - When an alternate filestore target is configured, Mattermost Cloud admins can generate an S3 presigned URL for exports using the ``/exportlink [job-id|zip file|latest]`` slash command. See the :ref:`Mattermost data migration ` documentation for details. Alternatively, Cloud and self-hosted admins can use the :ref:`mmctl export generate-presigned-url ` command to generate a presigned URL directly from mmctl. + - Generating an S3 presigned URL requires the feature flag ``EnableExportDirectDownload`` to be set to ``true``, the storage must be compatible with generating an S3 link, and this experimental configuration setting must be set to ``true``. Presigned URLs for exports aren't supported for systems with shared storage.