{"id":11385,"library":"nest-sftp","title":"Nest SFTP Module","description":"nest-sftp is a NestJS framework module that provides a wrapper around the `ssh2-sftp-client` library, enabling SFTP client capabilities within a NestJS application. It integrates SFTP connection management directly into the NestJS dependency injection system, allowing for easy configuration and use of SFTP operations. The current stable version is 3.1.0, which includes support for NestJS 11. While minor releases and bug fixes occur periodically, major version updates are less frequent, often coinciding with significant changes or new NestJS version support. Key differentiators include its seamless integration with Nest's module system, supporting both synchronous (`forRoot`) and asynchronous (`forRootAsync`) configuration patterns, and the ability to inject a configured `SftpClientService` directly into other services for file transfer operations.","status":"active","version":"3.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/benMain/nest-sftp","tags":["javascript","nest","sftp","lambda","typescript"],"install":[{"cmd":"npm install nest-sftp","lang":"bash","label":"npm"},{"cmd":"yarn add nest-sftp","lang":"bash","label":"yarn"},{"cmd":"pnpm add nest-sftp","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for NestJS module integration.","package":"@nestjs/common","optional":false},{"reason":"Peer dependency for NestJS module integration.","package":"@nestjs/core","optional":false}],"imports":[{"note":"This is the main module for registering SFTP capabilities in NestJS. Use `forRoot` or `forRootAsync`.","wrong":"const SftpModule = require('nest-sftp');","symbol":"SftpModule","correct":"import { SftpModule } from 'nest-sftp';"},{"note":"This service is injected into your application's providers to perform SFTP operations. It's automatically exposed by SftpModule.","wrong":"import { SftpClientService } from 'nest-sftp/sftp-client.service';","symbol":"SftpClientService","correct":"import { SftpClientService } from 'nest-sftp';"},{"note":"While nest-sftp uses `ssh2-sftp-client`, its `ConnectConfig` interface comes directly from the underlying library for type consistency.","wrong":"import { ConnectConfig } from 'nest-sftp';","symbol":"ConnectConfig","correct":"import { ConnectConfig } from 'ssh2-sftp-client';"}],"quickstart":{"code":"import { Module, Injectable, Logger } from '@nestjs/common';\nimport { SftpModule, SftpClientService } from 'nest-sftp';\nimport { ConnectConfig } from 'ssh2-sftp-client';\n\n@Injectable()\nclass ConfigService {\n  getSftpConnectionInfo(): ConnectConfig {\n    // In a real app, fetch these from environment variables or a configuration store\n    return {\n      host: process.env.SFTP_HOST ?? 'sftp.example.com',\n      port: parseInt(process.env.SFTP_PORT ?? '22', 10),\n      username: process.env.SFTP_USERNAME ?? 'user',\n      password: process.env.SFTP_PASSWORD ?? 'password',\n      // Optional: debug logging\n      debug: console.log\n    };\n  }\n}\n\n@Injectable()\nexport class AppService {\n  private readonly logger = new Logger(AppService.name);\n  constructor(private readonly sftpClient: SftpClientService) {}\n\n  async runSftpExample(): Promise<void> {\n    try {\n      this.logger.log('Attempting to list SFTP directory...');\n      const list = await this.sftpClient.list('/remote/path');\n      this.logger.log(`Listed directory: ${JSON.stringify(list.map(f => f.name))}`);\n\n      const remoteFile = `/remote/path/test-${Date.now()}.txt`;\n      const localContent = 'Hello SFTP from NestJS!';\n      const buffer = Buffer.from(localContent);\n\n      this.logger.log(`Uploading file to ${remoteFile}`);\n      await this.sftpClient.upload(buffer, remoteFile);\n      this.logger.log('File uploaded successfully.');\n\n      this.logger.log(`Downloading file from ${remoteFile}`);\n      const downloadedBuffer = await this.sftpClient.download(remoteFile);\n      this.logger.log(`Downloaded content: ${downloadedBuffer.toString()}`);\n\n      this.logger.log(`Deleting file ${remoteFile}`);\n      await this.sftpClient.delete(remoteFile);\n      this.logger.log('File deleted successfully.');\n\n    } catch (error) {\n      this.logger.error('SFTP operation failed:', error.message);\n    }\n  }\n}\n\n@Module({\n  imports: [\n    SftpModule.forRootAsync(\n      {\n        useFactory: (configService: ConfigService) => {\n          return configService.getSftpConnectionInfo();\n        },\n        inject: [ConfigService],\n        imports: [ConfigService],\n      }\n    ),\n  ],\n  controllers: [],\n  providers: [ConfigService, AppService],\n  exports: [ConfigService, AppService]\n})\nexport class AppModule {\n  constructor(private readonly appService: AppService) {\n    // Kick off the SFTP example when the app starts\n    // This would typically be triggered by an endpoint or lifecycle hook in a real app\n    this.appService.runSftpExample();\n  }\n}\n","lang":"typescript","description":"This quickstart demonstrates registering the SftpModule asynchronously, injecting SftpClientService, and performing basic SFTP operations like listing, uploading, downloading, and deleting files."},"warnings":[{"fix":"Review the official README for the latest configuration patterns, especially `forRootAsync` usage. Re-evaluate `SftpModule` imports and `SftpClientService` injection.","message":"Version 3.0.0 introduced breaking changes due to potential updates in its underlying dependency `ssh2-sftp-client` or internal module structure, although the changelog does not explicitly detail them. Users upgrading from v2.x should review their module configuration and SFTP client usage.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Migrate `SftpModule` configuration to `forRootAsync` pattern, especially if you need to inject other services (like `ConfigService`) to retrieve SFTP connection details.","message":"The `SftpModule` configuration methods (`forRoot`, `forRootAsync`) might have changed signature or preferred usage across major versions. The documentation emphasizes `forRootAsync` which suggests that the synchronous `forRoot` might have limitations or be less recommended in newer versions.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"When providing passwords, ensure that `\\` is escaped to `\\\\`. Test passwords containing `!` or `(` thoroughly, as they might interact poorly with shell environments or configuration parsing, even if the library itself handles them.","message":"Special characters in SFTP passwords, specifically backslashes (`\\`), exclamation marks (`!`), and opening parentheses (`(`), need careful handling. Backslashes usually require escaping (`\\\\`).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For production environments, ensure the `debug` property is either omitted or points to a custom logging function that sanitizes or redacts sensitive information before outputting to logs.","message":"The `debug` option for `ConnectConfig` directly uses a `console.log` function. Exposing raw sensitive connection details in production logs via this can be a security risk.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always test new `nest-sftp` versions against your specific NestJS version. Consult the `nest-sftp` changelog for explicit NestJS version support updates, such as the v3.1.0 update for NestJS 11.","message":"While `nest-sftp` supports a wide range of NestJS peer dependencies (7-11), ensure compatibility by testing thoroughly if you are on the edges of this range or using a pre-release NestJS version.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `SftpModule.forRoot()` or `SftpModule.forRootAsync()` is properly imported in your `AppModule` or a shared module that is imported by the consuming module. Remember that `SftpModule` is often made global as per the documentation.","cause":"The SftpModule was not imported or configured correctly, or `SftpClientService` is being injected outside a module that imports `SftpModule`.","error":"Nest can't resolve dependencies of the SftpClientService (?). Please make sure that the argument SftpClientService at index [0] is available in the SftpModule context."},{"fix":"Verify `host` and `port` in your `ConnectConfig`. Check network connectivity and firewall rules between your application and the SFTP server. Increase the `timeout` option in `ConnectConfig` if the server is known to be slow.","cause":"The SFTP server did not respond within the configured timeout period, often due to incorrect host/port, network issues, or a firewall blocking the connection.","error":"Error: Timeout while waiting for handshake"},{"fix":"Double-check the `username` and `password` for accuracy, including any special character escaping requirements. Ensure the user has the necessary permissions on the SFTP server.","cause":"Incorrect username or password provided in the `ConnectConfig`.","error":"Error: Authentication failure. User: [username]"},{"fix":"Update `nest-sftp` to the latest version (v2.x or later added `forRootAsync`). If on a recent version, check your `tsconfig.json` for module resolution settings and ensure proper project setup.","cause":"You might be using an older version of `nest-sftp` that does not support `forRootAsync`, or there's a TypeScript compilation issue.","error":"TypeError: SftpModule.forRootAsync is not a function"}],"ecosystem":"npm"}