Appearance
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
| Driver | Description |
|---|---|
local | Local filesystem storage |
s3 | Amazon S3 or S3-compatible (e.g., MinIO, Backblaze B2) |
Sensitive Fields
The following storage fields are automatically encrypted at rest using the server SECRET:
accessKeysecretKeyserviceAccount(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"
}
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique provider name (used in odp_files.storage) |
value | object | Yes | Driver-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"
}| Field | Required | Description |
|---|---|---|
driver | Yes | Must be local |
root | Yes | Absolute 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
}| Field | Required | Description |
|---|---|---|
driver | Yes | Must be s3 |
bucket | Yes | S3 bucket name |
region | Yes | AWS region |
accessKey | Yes | AWS access key ID |
secretKey | Yes | AWS secret access key |
endpoint | No | Custom endpoint URL (for MinIO, Backblaze, etc.) |
acl | No | S3 ACL (private, public-read, etc.) |
serverSideEncryption | No | SSE algorithm (AES256, aws:kms) |
forcePathStyle | No | Use 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:
- Reads all
system_storage_providersettings from the database - Decrypts sensitive fields
- Instantiates driver instances (local or S3)
- 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)
| Column | Value/Description |
|---|---|
extension_key | system_storage_provider |
name | Provider name (e.g., local, s3-media) |
value | JSON config with encrypted sensitive fields |
Environment Variables
| Variable | Default | Description |
|---|---|---|
STORAGE_LOCAL_ROOT | ./uploads | Default local storage directory |
SECRET | — | Used for encrypting sensitive fields |