Skip to content

Storage Providers Management

Overview

ODP supports multiple storage backends for file storage. Storage providers are configured via the admin API and stored in odp_extension_settings (with extension_key = 'system_storage_provider'). After any change, the StorageManager is re-initialized to pick up the new configuration.

Supported Drivers

DriverDescription
localLocal filesystem storage
s3Amazon S3 or S3-compatible (e.g., MinIO, Backblaze B2)

Sensitive Fields

The following storage fields are automatically encrypted at rest using the server SECRET:

  • accessKey
  • secretKey
  • serviceAccount (for GCS)
  • accountKey (for Azure)
  • password

When reading provider configs via the API, sensitive fields are masked as "********".


Endpoints

All endpoints require Admin access.

GET /system/storage-providers

List all configured storage providers.

Response:

json
{
  "data": [
    {
      "id": 1,
      "name": "local",
      "extension_key": "system_storage_provider",
      "value": {
        "driver": "local",
        "root": "/uploads"
      }
    },
    {
      "id": 2,
      "name": "s3-media",
      "extension_key": "system_storage_provider",
      "value": {
        "driver": "s3",
        "bucket": "my-media-bucket",
        "region": "us-east-1",
        "accessKey": "AKID...",
        "secretKey": "********",
        "acl": "public-read"
      }
    }
  ]
}

GET /system/storage-providers/:name

Get a specific provider by name.

URL Parameters:

  • name — Provider name

Response: Single provider object (with sensitive fields masked).

Error: 404 Not Found if provider does not exist.


POST /system/storage-providers

Create a new storage provider.

Request Body:

json
{
  "name": "s3-archive",
  "value": {
    "driver": "s3",
    "bucket": "my-archive-bucket",
    "region": "eu-west-1",
    "accessKey": "AKID...",
    "secretKey": "my-secret"
  }
}
FieldTypeRequiredDescription
namestringYesUnique provider name (used in odp_files.storage)
valueobjectYesDriver-specific configuration

Response: 201 Created

json
{
  "data": { "id": 3 }
}

Side Effect: storageManager.initialize() is called to reload all providers.


PATCH /system/storage-providers/:id

Update a storage provider's configuration.

URL Parameters:

  • id — Provider record ID (integer)

Request Body:

json
{
  "value": {
    "driver": "s3",
    "bucket": "updated-bucket",
    "region": "us-west-2",
    "accessKey": "NEW_ACCESS_KEY",
    "secretKey": "NEW_SECRET_KEY"
  }
}

Response:

json
{
  "data": { "id": 3 }
}

Side Effect: storageManager.initialize() reloads all providers.

To keep an existing secret, send the masked value "********" — it will not overwrite the stored encrypted value.


DELETE /system/storage-providers/:id

Delete a storage provider.

URL Parameters:

  • id — Provider record ID

Response: 204 No Content

Side Effect: storageManager.initialize() reloads providers. Files that referenced this provider by name will fail to serve.


Driver Configurations

Local Driver

json
{
  "driver": "local",
  "root": "/var/uploads"
}
FieldRequiredDescription
driverYesMust be local
rootYesAbsolute path to storage directory

Defaults to STORAGE_LOCAL_ROOT environment variable if not set.


S3 Driver

json
{
  "driver": "s3",
  "bucket": "my-bucket",
  "region": "us-east-1",
  "accessKey": "AKIAIOSFODNN7EXAMPLE",
  "secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "endpoint": "https://s3.us-east-1.amazonaws.com",
  "acl": "private",
  "serverSideEncryption": "AES256",
  "forcePathStyle": false
}
FieldRequiredDescription
driverYesMust be s3
bucketYesS3 bucket name
regionYesAWS region
accessKeyYesAWS access key ID
secretKeyYesAWS secret access key
endpointNoCustom endpoint URL (for MinIO, Backblaze, etc.)
aclNoS3 ACL (private, public-read, etc.)
serverSideEncryptionNoSSE algorithm (AES256, aws:kms)
forcePathStyleNoUse path-style URLs (required for some S3-compatible services)

Storage Manager

The StorageManager is a singleton that manages active driver instances. When initialize() is called:

  1. Reads all system_storage_provider settings from the database
  2. Decrypts sensitive fields
  3. Instantiates driver instances (local or S3)
  4. Makes drivers available via storageManager.getDriver(name)

The manager always has a local driver as fallback (using STORAGE_LOCAL_ROOT).


Data Model

Storage providers are stored in odp_extension_settings:

odp_extension_settings (storage providers)

ColumnValue/Description
extension_keysystem_storage_provider
nameProvider name (e.g., local, s3-media)
valueJSON config with encrypted sensitive fields

Environment Variables

VariableDefaultDescription
STORAGE_LOCAL_ROOT./uploadsDefault local storage directory
SECRETUsed for encrypting sensitive fields

ODP Internal API Documentation