Skip to main content

Integrating S3-Compatible Asset Storage

This guide demonstrates how to integrate S3-compatible asset storage into your Vendure application using multiple cloud storage platforms. You'll learn to configure a single, platform-agnostic storage solution that works seamlessly with AWS S3, DigitalOcean Spaces, MinIO, CloudFlare R2, and Supabase Storage.

Working Example Repository

Info

This guide is based on the s3-file-storage example. Refer to the complete working code for full implementation details.

Prerequisites

  • Node.js 20+ with npm package manager
  • An existing Vendure project created with the Vendure create command
  • An account with one of the supported S3-compatible storage providers

S3-Compatible Storage Provider Setup

Configure your chosen storage provider by following the setup instructions for your preferred platform:

Setting up AWS S3

  1. Create an S3 Bucket

    • Navigate to AWS S3 Console
    • Click "Create bucket"
    • Enter a unique bucket name (e.g., my-vendure-assets)
    • Choose your preferred AWS region
    • Configure permissions as needed for public asset access
  2. Create IAM User with S3 Permissions

    • Go to AWS IAM Console
    • Navigate to "Users" and click "Create user"
    • Enter username and proceeed to Set Permissions
    • Select the Attach existing policies directly option
    • Attach the AmazonS3FullAccess policy (or create a custom policy with minimal permissions)
  3. Generate Access Keys

    • After creating the user, click on the user name
    • Go to "Security credentials" tab
    • Click "Create access key" and select "Application running on AWS service"
    • Copy the Access Key ID and Secret Access Key (Download the CSV file if needed)
  4. Environment Variables

    Bash
    # AWS S3 ConfigurationS3_BUCKET=my-vendure-assetsS3_ACCESS_KEY_ID=AKIA...S3_SECRET_ACCESS_KEY=wJalrXUtn...S3_REGION=us-east-1# Leave S3_ENDPOINT empty for AWS S3# Leave S3_FORCE_PATH_STYLE empty for AWS S3
    AWS S3 Setup

Vendure Configuration

Configure your Vendure application to use S3-compatible asset storage by modifying your vendure-config.ts:

src/vendure-config.ts
import { VendureConfig } from '@vendure/core';import { // [!code highlight]  AssetServerPlugin, // [!code highlight]  configureS3AssetStorage // [!code highlight]} from '@vendure/asset-server-plugin'; // [!code highlight]import 'dotenv/config';import path from 'path';const IS_DEV = process.env.APP_ENV === 'dev';export const config: VendureConfig = {  // ... other configuration options  plugins: [    AssetServerPlugin.init({ // [!code highlight]      route: 'assets', // [!code highlight]      assetUploadDir: path.join(__dirname, '../static/assets'), // [!code highlight]      assetUrlPrefix: IS_DEV ? undefined : 'https://www.my-shop.com/assets/', // [!code highlight] // [!code highlight]      // S3-Compatible Storage Configuration // [!code highlight]      // Dynamically switches between local storage and S3 based on environment // [!code highlight]      storageStrategyFactory: process.env.S3_BUCKET // [!code highlight]        ? configureS3AssetStorage({ // [!code highlight]            bucket: process.env.S3_BUCKET, // [!code highlight]            credentials: { // [!code highlight]              accessKeyId: process.env.S3_ACCESS_KEY_ID!, // [!code highlight]              secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!, // [!code highlight]            }, // [!code highlight]            nativeS3Configuration: { // [!code highlight]              // Platform-specific endpoint configuration // [!code highlight]              endpoint: process.env.S3_ENDPOINT, // [!code highlight]              region: process.env.S3_REGION, // [!code highlight]              forcePathStyle: process.env.S3_FORCE_PATH_STYLE === 'true', // [!code highlight]              signatureVersion: 'v4', // [!code highlight]            }, // [!code highlight]          }) // [!code highlight]        : undefined, // Fallback to local storage when S3 not configured // [!code highlight]    }), // [!code highlight]    // ... other plugins  ],};
Note

IMPORTANT: The configuration uses a conditional approach - when S3_BUCKET is set, it activates S3 storage; otherwise, it falls back to local file storage. This enables seamless development-to-production transitions.

Environment Configuration

Create a .env file in your project root with your chosen storage provider configuration:

.env
# Basic Vendure ConfigurationAPP_ENV=devSUPERADMIN_USERNAME=superadminSUPERADMIN_PASSWORD=superadminCOOKIE_SECRET=your-cookie-secret-32-characters-min# S3-Compatible Storage ConfigurationS3_BUCKET=your-bucket-nameS3_ACCESS_KEY_ID=your-access-key-idS3_SECRET_ACCESS_KEY=your-secret-access-keyS3_REGION=your-regionS3_ENDPOINT=your-endpoint-urlS3_FORCE_PATH_STYLE=true-or-false

Preconfigured environment examples for each storage provider are available in the s3-file-storage example repository.

Testing Your Configuration

Verify your S3 storage configuration works correctly:

  1. Start your Vendure server:

    npm run dev:server
  2. Access the Dashboard:

  3. Test asset upload:

    • Navigate to "Catalog" → "Assets"
    • Click "Upload assets"
    • Select a test image and upload
    • Verify the image appears in the asset gallery
  4. Verify storage backend:

    • Check your S3 bucket/storage service for the uploaded file
    • Confirm the asset URL is accessible

Advanced Configuration

Custom Asset URL Prefix

For production deployments with CDN or custom domains:

src/vendure-config.ts
AssetServerPlugin.init({  route: 'assets',  assetUrlPrefix: 'https://cdn.yourdomain.com/assets/', // [!code highlight]  storageStrategyFactory: process.env.S3_BUCKET    ? configureS3AssetStorage({        // ... S3 configuration      })    : undefined,});

Environment-Specific Configuration

Use different buckets for different environments:

Bash
# DevelopmentS3_BUCKET=vendure-dev-assets# StagingS3_BUCKET=vendure-staging-assets# ProductionS3_BUCKET=vendure-prod-assets

Migration Between Platforms

Switching between storage providers requires updating only the environment variables:

Bash
# From AWS S3 to CloudFlare R2# Change these variables:S3_ENDPOINT=https://account-id.r2.cloudflarestorage.comS3_FORCE_PATH_STYLE=true# Keep the same bucket name and credentials structure

Troubleshooting

Common Issues

  1. "Access Denied" Errors:

    • Verify your access key has proper permissions
    • Check bucket policies allow the required operations
    • Ensure credentials are correctly set in environment variables
  2. "Bucket Not Found" Errors:

    • Verify bucket name matches exactly (case-sensitive)
    • Check that S3_REGION matches your bucket's region
    • For MinIO/R2, ensure S3_FORCE_PATH_STYLE=true
  3. Assets Not Loading:

    • Verify bucket has public read access (if needed)
    • Check CORS configuration for browser-based access
    • Ensure assetUrlPrefix matches your actual domain
  4. Connection Timeout Issues:

    • Verify S3_ENDPOINT URL is correct and accessible
    • Check firewall settings for outbound connections
    • For self-hosted MinIO, ensure server is running and accessible

Conclusion

You now have a robust, platform-agnostic S3-compatible asset storage solution integrated with your Vendure application. This configuration provides:

  • Seamless switching between storage providers via environment variables
  • Development-to-production workflow with local storage fallback
  • Built-in compatibility with major S3-compatible services
  • Production-ready configuration patterns

The unified approach eliminates the need for custom storage plugins while maintaining flexibility across different cloud storage platforms. Your assets will be reliably stored and served regardless of which S3-compatible provider you choose.

Next Steps

  • Set up CDN integration for improved global asset delivery
  • Implement backup strategies for critical assets
  • Configure monitoring and alerting for storage operations
  • Consider implementing asset optimization and transformation workflows
Was this chapter helpful?
Report Issue
Edited Feb 2, 2026·Edit this page