# How to Configure S3 or MinIO as the Media Storage Backend in OpenWA

> Learn how to configure S3 or MinIO as the media storage backend in OpenWA. Switch from local disk to object storage by setting environment variables for seamless integration.

- Repository: [Yudhi Armyndharis/OpenWA](https://github.com/rmyndharis/OpenWA)
- Tags: how-to-guide
- Published: 2026-05-21

---

**Set `STORAGE_TYPE=s3` in your environment variables and provide the endpoint, access credentials, region, and bucket name to switch OpenWA from local disk storage to any S3-compatible object store including AWS S3 or MinIO.**

OpenWA (Open WhatsApp) is an open-source automation framework that defaults to storing media files in a local `./data/media` directory. According to the rmyndharis/OpenWA source code, you can configure S3 or MinIO as the media storage backend by updating the `storage` configuration section and providing specific connection parameters that the `StorageService` consumes during initialization.

## Understanding the Storage Architecture

OpenWA handles all incoming and outgoing media files (images, videos, documents) through the **`StorageService`** located in [[`src/common/storage/storage.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts). By default, the service operates in `local` mode, writing files to the filesystem. To switch to cloud storage, you must change the `config.storage.type` value to `'s3'`, which triggers the S3-compatible client initialization path.

## Configuring S3 or MinIO as the Media Storage Backend

### Set the Storage Type to S3

The application determines which storage backend to instantiate based on the `storage.type` configuration value. In [[`src/config/configuration.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/config/configuration.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/config/configuration.ts#L80-L84), the default is defined as `'local'`, but you can override this via the `STORAGE_TYPE` environment variable.

```bash
STORAGE_TYPE=s3

```

When `STORAGE_TYPE` is set to `s3`, the factory method in `StorageService` instantiates the S3 client instead of the local filesystem adapter.

### Provide S3/MinIO Connection Credentials

The S3 client initialization in [[`src/common/storage/storage.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts#L40-L58) reads configuration from either environment variables or the `config.storage.s3` object. The following parameters are required:

- **`S3_ENDPOINT`** / `storage.s3.endpoint` — The URL of the object store API (e.g., `http://localhost:9000` for MinIO or `https://s3.amazonaws.com` for AWS).
- **`S3_ACCESS_KEY_ID`** / `storage.s3.accessKeyId` — The access key ID for authentication.
- **`S3_SECRET_ACCESS_KEY`** / `storage.s3.secretAccessKey` — The secret access key for authentication.
- **`S3_REGION`** / `storage.s3.region` — The AWS region (any valid string works for MinIO).
- **`S3_BUCKET`** / `storage.s3.bucket` — The target bucket name (defaults to `openwa` if not specified).

The source code explicitly sets **`forcePathStyle: true`** in the S3 client configuration, ensuring compatibility with MinIO and other non-AWS S3-compatible services that use path-style addressing.

## Configuration Examples for OpenWA

### MinIO Configuration

For a local MinIO instance running on port 9000, configure your `.env` file as follows:

```dotenv
STORAGE_TYPE=s3
S3_ENDPOINT=http://localhost:9000
S3_ACCESS_KEY_ID=minioadmin
S3_SECRET_ACCESS_KEY=minioadmin
S3_REGION=us-east-1
S3_BUCKET=openwa-media

```

### AWS S3 Configuration

To use Amazon S3 as the backend:

```dotenv
STORAGE_TYPE=s3
S3_ENDPOINT=https://s3.amazonaws.com
S3_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY
S3_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_KEY
S3_REGION=us-east-1
S3_BUCKET=openwa-media

```

### Programmatic Override

If you prefer to hardcode values directly in the application configuration instead of using environment variables, modify [[`src/config/configuration.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/config/configuration.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/config/configuration.ts):

```typescript
export default () => ({
  // ... other config
  storage: {
    type: 's3',
    s3: {
      endpoint: 'http://localhost:9000',
      accessKeyId: 'minioadmin',
      secretAccessKey: 'minioadmin',
      region: 'us-east-1',
      bucket: 'openwa-media',
    },
  },
});

```

## S3 Client Initialization Details

When the application starts, the `StorageService` performs the following operations as implemented in the source code:

1. **Client Creation** (lines 40-58): Constructs the S3 client using the provided credentials and endpoint, with `forcePathStyle: true` enabled for MinIO compatibility.
2. **Bucket Initialization** (lines 70-90): Calls `initializeS3Bucket()` to check if the configured bucket exists. If the bucket is missing, the service automatically creates it with private ACL settings.

After restarting the application (e.g., `npm run start:prod` or your Docker container), verify the configuration by checking the logs for the message:

```

[StorageService] S3 bucket 'openwa-media' is available

```

Once this message appears, all media uploads and downloads will route through the configured S3 or MinIO endpoint instead of the local filesystem.

## Summary

- OpenWA uses the `StorageService` class to abstract media storage operations, supporting both local filesystem and S3-compatible backends.
- Set `STORAGE_TYPE=s3` to switch from local storage to an object store.
- Provide `S3_ENDPOINT`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_REGION`, and `S3_BUCKET` to authenticate and target the correct bucket.
- The S3 client forces path-style requests, ensuring MinIO works without additional configuration.
- The application automatically creates the specified bucket if it does not already exist during startup.

## Frequently Asked Questions

### Does OpenWA support MinIO as a storage backend?

Yes. OpenWA supports any S3-compatible object store, including MinIO, DigitalOcean Spaces, and Wasabi. The S3 client explicitly enables `forcePathStyle: true` in [[`src/common/storage/storage.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts#L40-L58), which is required for MinIO compatibility.

### What happens if the S3 bucket does not exist?

OpenWA automatically creates the bucket during initialization if it is missing. The `initializeS3Bucket()` method in [[`src/common/storage/storage.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts#L70-L90) checks for bucket existence and executes a `CreateBucket` command when necessary, applying private ACL permissions by default.

### Can I migrate existing local media to S3 after switching the configuration?

The configuration change only affects new media operations. Existing files stored locally in `./data/media` will not be automatically migrated to S3. You must manually upload existing files to your S3 bucket and update any database references if you require historical media to be accessible via the new backend.

### Is it possible to use different storage backends for different media types?

No. According to the current implementation in [[`src/common/storage/storage.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts)](https://github.com/rmyndharis/OpenWA/blob/main/src/common/storage/storage.service.ts), OpenWA initializes a single global storage backend at startup. All media—images, videos, audio, and documents—use the same storage configuration defined by `STORAGE_TYPE` and the associated credentials.