A powerful and flexible NestJS module for integrating MinIO object storage into your NestJS applications. This package provides a seamless way to interact with MinIO, an open-source object storage service compatible with Amazon S3.
- Features
- Installation
- Requirements
- Quick Start
- Configuration
- API Reference
- Contributing
- License
- Support
- π Easy integration with NestJS applications
- π― Powerful decorators for blazing-fast implementation
@FileUpload()
- Handles multiple file uploads with built-in validation@FileField()
- Swagger-ready DTO field decorator@FileSchemaField()
- Mongoose schema integration for file fields
- π Complete MinIO operations support (upload, download, delete, etc.)
- π§ Configurable module options
- π― TypeScript support
- π Swagger documentation support
- π RxJS integration
npm install nestjs-minio-backend
- Node.js >= 20.15.0
- NestJS >= 11.0.0
- MinIO Server (running instance)
This module requires the following peer dependencies:
{
"@nestjs/common": "^11.0.12",
"@nestjs/core": "^11.0.12",
"minio": "^8.0.5",
"rxjs": "^7.8.2",
"@nestjs/mongoose": "^11.0.2",
"@nestjs/platform-express": "^11.0.12",
"@nestjs/swagger": "^11.0.7",
"class-validator": "^0.14.1"
}
- First, set up your MinIO configuration:
Create a config/minio.config.ts
file:
import { registerAs } from '@nestjs/config';
export default registerAs('minio', () => ({
endPoint: process.env.MINIO_ENDPOINT || 'localhost',
externalEndPoint:
process.env.MINIO_EXTERNAL_ENDPOINT ||
process.env.MINIO_ENDPOINT ||
'localhost',
port: parseInt(process.env.MINIO_PORT || '9000', 10),
useSSL: process.env.MINIO_USE_HTTPS === 'true',
externalUseSSL: process.env.MINIO_EXTERNAL_ENDPOINT_USE_HTTPS === 'true',
accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin',
secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin',
urlExpiryHours: parseInt(process.env.MINIO_URL_EXPIRY_HOURS || '2', 10),
buckets: {
private: [
process.env.MINIO_MEDIA_FILES_BUCKET || 'media-files-bucket',
process.env.MINIO_CHAIN_ICONS_BUCKET || 'chain-icons',
],
public: [process.env.MINIO_STATIC_FILES_BUCKET || 'static-files-bucket'],
},
region: process.env.MINIO_REGION,
}));
Create a .env
file in your project root:
MINIO_ENDPOINT=your-minio-endpoint
MINIO_PORT=9000
MINIO_USE_HTTPS=false
MINIO_ACCESS_KEY=your-access-key
MINIO_SECRET_KEY=your-secret-key
MINIO_MEDIA_FILES_BUCKET=media-files-bucket
MINIO_STATIC_FILES_BUCKET=static-files-bucket
MINIO_URL_EXPIRY_HOURS=2
Then, in your app.module.ts
:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MinioModule } from 'nestjs-minio-backend';
import minioConfig from './config/minio.config';
@Module({
imports: [
ConfigModule.forRoot({
load: [minioConfig],
}),
MinioModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => configService.get('minio'),
}),
],
})
export class AppModule {}
This configuration approach provides:
- π Environment-based configuration
- π― Type-safe configuration using TypeScript
- π Default values for local development
- π Organized bucket management
- π Support for different endpoints (internal/external)
- Create your DTO with file field:
import { FileField } from 'nestjs-minio-backend';
export class CreateUserDto {
@FileField({
bucketName: 'profiles',
required: true,
description: 'User profile picture'
})
profilePicture: Express.Multer.File;
}
- Use the FileUpload decorator in your controller:
import { FileUpload } from 'nestjs-minio-backend';
import { CreateUserDto } from './dto/create-user.dto';
@Controller('users')
export class UserController {
@Post()
@FileUpload([
{ name: 'profilePicture', bucketName: 'profiles', required: true }
])
async createUser(@Body() createUserDto: CreateUserDto) {
// The file is automatically uploaded to MinIO
// You can access the file URL from the DTO
return createUserDto;
}
@Post('multiple')
@FileUpload([
{ name: 'documents', bucketName: 'docs', maxCount: 3 }
])
async uploadMultiple(@UploadedFiles() files: Array<Express.Multer.File>) {
return files; // Files are automatically uploaded to MinIO
}
}
- (Optional) Add file fields to your Mongoose schema:
import { FileSchemaField } from 'nestjs-minio-backend';
@Schema()
export class User {
@FileSchemaField({
bucketName: 'profiles',
required: true
})
avatar: string; // Automatically stores the MinIO object URL
}
These decorators provide:
- π Zero-configuration file uploads
- π Automatic Swagger documentation
- β Built-in validation
- π Seamless MongoDB integration
- π― Type safety with TypeScript
The module accepts the following configuration options:
interface IMinioModuleOptions {
// Required options
endPoint: string; // MinIO server endpoint
port: number; // MinIO server port
useSSL: boolean; // Whether to use SSL for connection
accessKey: string; // MinIO access key
secretKey: string; // MinIO secret key
urlExpiryHours: number; // Expiry time for signed URLs in hours
// Optional options
region?: string; // MinIO region
externalEndPoint?: string; // External endpoint for public access
externalUseSSL?: boolean; // Whether to use SSL for external endpoint
// Bucket configuration
buckets: {
private: string[]; // Array of private bucket names
public: string[]; // Array of public bucket names
};
}
const minioConfig: IMinioModuleOptions = {
endPoint: 'minio.example.com',
port: 9000,
useSSL: false,
accessKey: 'your-access-key',
secretKey: 'your-secret-key',
urlExpiryHours: 2,
// Optional settings
region: 'us-east-1',
externalEndPoint: 'public.minio.example.com',
externalUseSSL: true,
// Bucket configuration
buckets: {
private: [
'media-files-bucket',
'user-uploads'
],
public: [
'static-files-bucket',
'public-assets'
]
}
};
# Required settings
MINIO_ENDPOINT=minio.example.com
MINIO_PORT=9000
MINIO_USE_HTTPS=false
MINIO_ACCESS_KEY=your-access-key
MINIO_SECRET_KEY=your-secret-key
MINIO_URL_EXPIRY_HOURS=2
# Optional settings
MINIO_REGION=us-east-1
MINIO_EXTERNAL_ENDPOINT=public.minio.example.com
MINIO_EXTERNAL_ENDPOINT_USE_HTTPS=true
# Bucket configuration
MINIO_MEDIA_FILES_BUCKET=media-files-bucket
MINIO_STATIC_FILES_BUCKET=static-files-bucket
- π Dual Endpoint Support: Configure both internal and external endpoints for flexible access
- π SSL Configuration: Separate SSL settings for internal and external endpoints
- β±οΈ URL Expiry: Configure signed URL expiration time
- π Bucket Organization: Separate configuration for private and public buckets
- π Default Values: Sensible defaults for local development
- π‘οΈ Type Safety: Full TypeScript support with interface definitions
If you prefer more control over the file handling process, you can use the MinioService directly:
import { MinioService } from 'nestjs-minio-backend';
@Injectable()
export class YourService {
constructor(private readonly minioService: MinioService) {}
async uploadFile(file: Express.Multer.File) {
const bucketName = 'your-bucket';
const objectName = `${Date.now()}-${file.originalname}`;
await this.minioService.upload(bucketName, objectName, file.buffer);
return { objectName };
}
}
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
async uploadFile(@UploadedFile() file: Express.Multer.File) {
const bucketName = 'my-bucket';
const objectName = `${Date.now()}-${file.originalname}`;
await this.minioService.upload(bucketName, objectName, file.buffer);
return {
message: 'File uploaded successfully',
objectName,
};
}
@Get('download/:objectName')
async downloadFile(@Param('objectName') objectName: string, @Res() res: Response) {
const bucketName = 'my-bucket';
const fileBuffer = await this.minioService.download(bucketName, objectName);
res.send(fileBuffer);
}
Handles file uploads with automatic MinIO integration.
@FileUpload([
{
name: string, // Field name in the request
bucketName: string, // MinIO bucket name
required?: boolean, // Whether the file is required
maxCount?: number, // Maximum number of files
maxSize?: number, // Maximum file size in bytes
mimeTypes?: string[] // Allowed MIME types
}
])
Swagger-ready DTO field decorator for file uploads.
@FileField({
bucketName: string, // MinIO bucket name
required?: boolean, // Whether the field is required
description?: string // Swagger description
})
Mongoose schema integration for file fields.
@FileSchemaField({
bucketName: string, // MinIO bucket name
required?: boolean // Whether the field is required
})
- Fork it (https://github.com/UtilKit/nestjs-minio-backend/fork)
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -am 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Create a new Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Mishhub
- π« GitHub Issues
- π¬ Discord Community
- π§ Email: support@example.com