Skip to main content
The S3 storage driver supports Amazon S3 and S3-compatible storage services like DigitalOcean Spaces, MinIO, Cloudflare R2, and Backblaze B2. It provides scalable, reliable cloud storage with built-in redundancy.

Installation

The S3 driver is included by default with Directus via the @directus/storage-driver-s3 package, which uses the AWS SDK v3.

Configuration

Configure S3 storage using environment variables:
# Define storage location
STORAGE_LOCATIONS="s3"

# Configure S3 driver
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-bucket"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_KEY="your-access-key-id"
STORAGE_S3_SECRET="your-secret-access-key"

Configuration Options

bucket
string
required
The S3 bucket name where files will be stored.
key
string
AWS access key ID. If not provided, uses default AWS credential chain (environment variables, IAM roles, etc.).
secret
string
AWS secret access key. Required if key is provided.
region
string
AWS region where the bucket is located (e.g., us-east-1, eu-west-1).
root
string
Optional path prefix for all files within the bucket.
endpoint
string
Custom S3 endpoint URL for S3-compatible services. Include protocol (http:// or https://).
forcePathStyle
boolean
Use path-style URLs instead of virtual-hosted-style. Required for some S3-compatible services.
acl
string
Access Control List for uploaded files. Options: private, public-read, public-read-write, authenticated-read, etc.
serverSideEncryption
string
Server-side encryption type: AES256, aws:kms, or aws:kms:dsse.
serverSideEncryptionKmsKeyId
string
KMS key ID for encryption when using aws:kms or aws:kms:dsse.
connectionTimeout
number
Connection timeout in milliseconds. Default: 5000.
socketTimeout
number
Socket timeout in milliseconds. Default: 120000.
maxSockets
number
Maximum number of concurrent sockets. Default: 500.
keepAlive
boolean
Enable HTTP keep-alive. Default: true.
tus.chunkSize
number
Chunk size for resumable uploads in bytes. Default: 5242880 (5 MiB). Minimum: 5242880 (5 MiB).

Examples

Amazon S3

STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-directus-files"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_KEY="AKIAIOSFODNN7EXAMPLE"
STORAGE_S3_SECRET="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

With Root Path

STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="shared-bucket"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_ROOT="directus/production"
STORAGE_S3_KEY="AKIAIOSFODNN7EXAMPLE"
STORAGE_S3_SECRET="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

IAM Role (EC2/ECS)

# Credentials automatically loaded from IAM role
STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-bucket"
STORAGE_S3_REGION="us-east-1"

Public Read Access

STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-bucket"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_ACL="public-read"
STORAGE_S3_KEY="AKIAIOSFODNN7EXAMPLE"
STORAGE_S3_SECRET="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Server-Side Encryption

STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-bucket"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_SERVER_SIDE_ENCRYPTION="AES256"
STORAGE_S3_KEY="AKIAIOSFODNN7EXAMPLE"
STORAGE_S3_SECRET="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

KMS Encryption

STORAGE_LOCATIONS="s3"
STORAGE_S3_DRIVER="s3"
STORAGE_S3_BUCKET="my-bucket"
STORAGE_S3_REGION="us-east-1"
STORAGE_S3_SERVER_SIDE_ENCRYPTION="aws:kms"
STORAGE_S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID="arn:aws:kms:us-east-1:123456789:key/12345678-1234-1234-1234-123456789012"
STORAGE_S3_KEY="AKIAIOSFODNN7EXAMPLE"
STORAGE_S3_SECRET="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

DigitalOcean Spaces

STORAGE_LOCATIONS="spaces"
STORAGE_SPACES_DRIVER="s3"
STORAGE_SPACES_BUCKET="my-space"
STORAGE_SPACES_REGION="nyc3"
STORAGE_SPACES_ENDPOINT="https://nyc3.digitaloceanspaces.com"
STORAGE_SPACES_KEY="your-access-key"
STORAGE_SPACES_SECRET="your-secret-key"

Cloudflare R2

STORAGE_LOCATIONS="r2"
STORAGE_R2_DRIVER="s3"
STORAGE_R2_BUCKET="my-bucket"
STORAGE_R2_REGION="auto"
STORAGE_R2_ENDPOINT="https://your-account-id.r2.cloudflarestorage.com"
STORAGE_R2_KEY="your-access-key-id"
STORAGE_R2_SECRET="your-secret-access-key"

MinIO

STORAGE_LOCATIONS="minio"
STORAGE_MINIO_DRIVER="s3"
STORAGE_MINIO_BUCKET="directus"
STORAGE_MINIO_REGION="us-east-1"
STORAGE_MINIO_ENDPOINT="http://minio:9000"
STORAGE_MINIO_FORCE_PATH_STYLE="true"
STORAGE_MINIO_KEY="minioadmin"
STORAGE_MINIO_SECRET="minioadmin"

Backblaze B2

STORAGE_LOCATIONS="b2"
STORAGE_B2_DRIVER="s3"
STORAGE_B2_BUCKET="my-bucket"
STORAGE_B2_REGION="us-west-001"
STORAGE_B2_ENDPOINT="https://s3.us-west-001.backblazeb2.com"
STORAGE_B2_KEY="your-key-id"
STORAGE_B2_SECRET="your-application-key"

Features

Resumable Uploads

The S3 driver supports TUS resumable uploads using S3 multipart upload:
  • Automatic chunking of large files
  • Resume interrupted uploads
  • Maximum upload size: 5 TiB
  • Maximum parts: 10,000
  • Minimum part size: 5 MiB

Multipart Upload

The driver implements S3 multipart upload from /packages/storage-driver-s3/src/index.ts:68-587:
  • Uploads are split into chunks
  • Chunks are uploaded in parallel (max 60 concurrent)
  • Failed parts can be retried independently
  • Incomplete uploads can be aborted

Performance Optimization

The driver is optimized for high-concurrency environments from /packages/storage-driver-s3/src/index.ts:89-107:
  • Custom connection pool with 500 max sockets (configurable)
  • HTTP keep-alive enabled by default
  • Configurable timeouts
  • Efficient memory usage with streams

Best Practices

IAM Permissions

Minimum required IAM permissions:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:GetObjectVersion",
        "s3:AbortMultipartUpload",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

CORS Configuration

If accessing files directly from the browser:
[
  {
    "AllowedOrigins": ["https://your-directus-instance.com"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag", "Upload-Offset", "Location"],
    "MaxAgeSeconds": 3000
  }
]

Bucket Lifecycle

Configure lifecycle rules to clean up incomplete multipart uploads:
{
  "Rules": [
    {
      "Id": "DeleteIncompleteMultipartUploads",
      "Status": "Enabled",
      "AbortIncompleteMultipartUpload": {
        "DaysAfterInitiation": 7
      }
    }
  ]
}

Cost Optimization

  • Use S3 Intelligent-Tiering for automatic cost optimization
  • Enable S3 Transfer Acceleration for faster uploads from distant regions
  • Consider CloudFront CDN for frequently accessed files
  • Monitor S3 request costs for high-traffic applications

Troubleshooting

Access Denied Errors

  1. Verify IAM permissions
  2. Check bucket policies
  3. Ensure credentials are correct
  4. Verify bucket exists in the specified region

Slow Upload Performance

Adjust concurrency and chunk size:
STORAGE_S3_TUS__CHUNK_SIZE="10485760"  # 10 MiB chunks
STORAGE_S3_MAX_SOCKETS="1000"

Connection Timeout Issues

Increase timeout values:
STORAGE_S3_CONNECTION_TIMEOUT="10000"  # 10 seconds
STORAGE_S3_SOCKET_TIMEOUT="300000"    # 5 minutes

Build docs developers (and LLMs) love