Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
SFTPServer
✓ const SFTPServer = require('node-sftp-server');
✗ import SFTPServer from 'node-sftp-server';
This package is CommonJS-only (published 2017) and does not support ESM `import` syntax directly. Using `require()` is the correct approach.
This quickstart code sets up a basic SFTP server listening on port 2222, demonstrating how to handle client connections, authenticate users (hardcoded 'testuser'/'testpass'), and implement basic `realpath`, `readfile`, and `writefile` operations. It requires a pre-generated private key for the server to start.
const SFTPServer = require('node-sftp-server');
const fs = require('fs');
const path = require('path');
// IMPORTANT: Generate a private key first:
// ssh-keygen -t rsa -b 2048 -N "" -f ssh_host_rsa_key
// Place 'ssh_host_rsa_key' in the same directory as this script.
const PRIVATE_KEY_PATH = path.join(__dirname, 'ssh_host_rsa_key');
if (!fs.existsSync(PRIVATE_KEY_PATH)) {
console.error(`Error: Private key file not found at ${PRIVATE_KEY_PATH}`);
console.error('Please generate one using: ssh-keygen -t rsa -b 2048 -N "" -f ssh_host_rsa_key');
process.exit(1);
}
const myserver = new SFTPServer({
privateKeyFile: PRIVATE_KEY_PATH,
debug: true // Enable for detailed console logging
});
myserver.listen(2222, () => {
console.log('SFTP Server listening on port 2222');
console.log('Connect with an SFTP client (e.g., sftp -P 2222 user@localhost)');
});
myserver.on('connect', (context, clientInfo) => {
console.log(`Client connected: ${clientInfo.ip} (User: ${context.username}, Method: ${context.method})`);
// Example: Basic password authentication
if (context.method === 'password' && context.username === 'testuser' && context.password === 'testpass') {
context.accept((session) => {
console.log('Authentication successful for testuser.');
session.on('realpath', (path, callback) => {
// Resolve paths relative to a user's 'home' directory
const userHome = path.join(__dirname, 'sftp_users', context.username);
fs.mkdirSync(userHome, { recursive: true }); // Ensure user's directory exists
callback(path.join(userHome, path.replace(/^\//, ''))); // Simple path resolution
});
session.on('readfile', (path, writableStream) => {
console.log(`Client requested to read file: ${path}`);
const filePath = path.join(__dirname, 'sftp_users', context.username, path.replace(/^\//, ''));
if (fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) {
fs.createReadStream(filePath).pipe(writableStream);
} else {
writableStream.destroy(new Error('File not found or not a file'));
}
});
session.on('writefile', (path, readableStream) => {
console.log(`Client requested to write file: ${path}`);
const filePath = path.join(__dirname, 'sftp_users', context.username, path.replace(/^\//, ''));
const dir = path.dirname(filePath);
fs.mkdirSync(dir, { recursive: true });
const writeStream = fs.createWriteStream(filePath);
readableStream.pipe(writeStream);
readableStream.on('end', () => console.log(`File written: ${filePath}`));
readableStream.on('error', (err) => console.error(`Write error: ${err.message}`));
});
// Other SFTP events like 'opendir', 'readdir', 'mkdir', 'rmdir', 'remove', 'rename', 'stat' would also be handled here
session.on('error', (err) => console.error(`Session error: ${err.message}`));
});
} else {
console.log('Authentication failed.');
context.reject(); // Reject all other methods/credentials
}
});
myserver.on('end', () => {
console.log('Client disconnected.');
});
myserver.on('error', (err) => {
console.error('SFTP Server Error:', err.message);
});
Errors
Common errors & fixes
ReferenceError: require is not defined
Attempting to use `require` in an ECMAScript Module (ESM) context, or `import`ing `node-sftp-server` directly in an ESM file.
fixEnsure your Node.js project is configured for CommonJS (e.g., remove `"type": "module"` from `package.json` or rename file to `.cjs`). If you must use ESM, consider dynamic `import()` or `createRequire` from the `module` built-in module, or use a modern SFTP server library.
Error: private key file missing or invalid
The SFTP server could not locate or read the specified private key file, or the file is malformed.
fixVerify that the path provided in `privateKeyFile` is correct and accessible. Ensure the file permissions allow the Node.js process to read it. If the key doesn't exist, generate one using `ssh-keygen -t rsa -b 2048 -N "" -f your_key_name`.
Error: listen EADDRINUSE: address already in use :::2222
The port the SFTP server is trying to listen on (e.g., 2222) is already occupied by another application or a previous instance of your server.
fixChange the port number in `myserver.listen(port)` to an unused port, or terminate the process currently using that port (e.g., `lsof -i :2222` on Linux/macOS, then `kill <PID>`).
Audit
Dependencies
ssh2requiredProvides the core SSH2 client and server modules in pure JavaScript for Node.js, on which SFTP functionality is built.
ssh2-streamsrequiredHandles the underlying SSH2 and SFTP(v3) client/server protocol streams.
tmprequiredUsed for managing temporary files during SFTP operations like downloads.