npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nestjs-minio-backend

v2.1.0

Published

NestJS module for MinIO integration

Readme

NestJS MinIO Backend

NPM Version Downloads Stats License TypeScript NestJS MinIO

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.

Table of Contents

Features

  • 🚀 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
  • 🗃️ @FileColumn() decorator for TypeORM or any class-based model
  • 📁 Complete MinIO operations support (upload, download, delete, etc.)
  • 🔧 Configurable module options
  • 🎯 TypeScript support
  • 📝 Swagger documentation support
  • 🔄 RxJS integration
  • 🧩 Optional @nestjs/mongoose integration (only required if you use @FileSchemaField)
  • 🤖 Automatic presigned URL detection even for raw QueryBuilder results

Installation

npm install nestjs-minio-backend

Requirements

  • Node.js >= 20.15.0
  • NestJS >= 11.0.0
  • MinIO Server (running instance)

Peer Dependencies

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"
}

Quick Start (Using Decorators)

  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:9000', // Format: "host" or "host:port"
  externalEndPoint:
    process.env.MINIO_EXTERNAL_ENDPOINT ||
    process.env.MINIO_ENDPOINT ||
    'localhost:9000', // Format: "host" or "host:port"
  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=minio:9000
MINIO_EXTERNAL_ENDPOINT=minio.example.com: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)
  1. 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;
}
  1. 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
  }
}
  1. (Optional) Add file fields to your persistence models:

TypeORM example

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
import { FileColumn } from 'nestjs-minio-backend';

@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @FileColumn({ bucketName: 'profiles' })
  @Column({ nullable: true })
  avatar?: string; // Stores the MinIO object path (bucket/objectName)
}

Mongoose example

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
  • 🤖 Automatic presigned URL generation even for raw QueryBuilder objects (bucket names are auto-detected from your MinIO config)
  • 🎯 Type safety with TypeScript
  • 🧩 Optional Mongoose dependency (install @nestjs/mongoose only if you plan to use @FileSchemaField)

Configuration

The module accepts the following configuration options:

interface IMinioModuleOptions {
  // Required options
  endPoint: string;          // MinIO server endpoint (format: "host" or "host:port", e.g., "minio:9000")
  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 (format: "host" or "host:port")
  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
  };
}

Configuration Example

const minioConfig: IMinioModuleOptions = {
  endPoint: 'minio.example.com:9000', // Port included in endpoint
  useSSL: false,
  accessKey: 'your-access-key',
  secretKey: 'your-secret-key',
  urlExpiryHours: 2,
  
  // Optional settings
  region: 'us-east-1',
  externalEndPoint: 'public.minio.example.com:9000', // Port included in endpoint
  externalUseSSL: true,
  
  // Bucket configuration
  buckets: {
    private: [
      'media-files-bucket',
      'user-uploads'
    ],
    public: [
      'static-files-bucket',
      'public-assets'
    ]
  }
};

Environment Variables Example

# Required settings
MINIO_ENDPOINT=minio: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=minio.example.com:9000
MINIO_EXTERNAL_ENDPOINT_USE_HTTPS=true

# Bucket configuration
MINIO_MEDIA_FILES_BUCKET=media-files-bucket
MINIO_STATIC_FILES_BUCKET=static-files-bucket

Key Features of the Configuration

  • 🔐 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

Manual Implementation (Without Decorators)

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 };
  }
}

Manual File Upload Example

@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,
  };
}

Manual File Download Example

@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);
}

API Reference

Decorators

@FileUpload()

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
  }
])

@FileField()

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
})

@FileSchemaField()

Mongoose schema integration for file fields (wraps @Prop plus @FileColumn metadata).

@FileSchemaField({
  bucketName: string,       // MinIO bucket name
  required?: boolean        // Whether the field is required
})

@FileColumn()

Database-agnostic decorator for marking entity properties that store MinIO object references. Works with TypeORM, Mongoose, or any class-based model.

@FileColumn({
  bucketName?: string        // Optionally enforce a specific bucket
})

Contributing

  1. Fork it (https://github.com/UtilKit/nestjs-minio-backend/fork)
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -am 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Create a new Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Mishhub

Support