SSH and SFTP client library for React Native on iOS and Android.
npm install @dylankenneally/react-native-ssh-sftpUpdate your Podfile to use the jim-lake's fork of NMSSH. Note that we use the forked version to give us a required later version of libssh. Your Podfile is located in your React Native project at ./ios/Podfile.
target '[your project's name]' do
pod 'NMSSH', :git => 'https://github.com/jim-lake/NMSSH.git' # <-- add this line
# ... rest of your target details ...
endAnd then run pod install in your ./ios directory.
cd ios
pod install
cd -Tip
Adding a postinstall script to your package.json file to run pod install after npm install is a good idea. The pod-install package is a good way to do this.
{
"scripts": {
"postinstall": "npx pod-install",
}
}If you are using Flipper to debug your app, it will already have a copy of OpenSSL included. This can cause issues with the version of OpenSSL that NMSSH uses. You can disable flipper by removing/commenting out the flipper_configuration => flipper_config, line in your Podfile.
No additional steps are needed for Android.
This project has been updated to use React Native v73 (the latest at the time of writing, Jan 2024) - which means that manual linking is not required.
All functions that run asynchronously where we have to wait for a result returns Promises that can reject if an error occurred.
Note
On iOS, this package currently doesn't support the simulator, you will need to have your app running on a physical device. If you would like to know more about this, see this issue. I'd welcome a PR to resolve this.
The new API separates connection and authentication into distinct operations, allowing for more flexible authentication workflows.
import SSHClient from '@dylankenneally/react-native-ssh-sftp';
const client = await SSHClient.connect("10.0.0.10", 22, "user");await client.authenticateWithPassword("password");const privateKey = "-----BEGIN RSA...";
await client.authenticateWithKey(privateKey);
// With passphrase
await client.authenticateWithKey(privateKey, "passphrase");const publicKey = "ssh-rsa AAAAB3NzaC1yc2EA......";
const signCallback = async (data) => {
// Your signing implementation
return signature;
};
await client.authenticateWithSignCallback(publicKey, signCallback);if (client.isAuthenticated()) {
// Client is ready for operations
}const client = await SSHClient.connect("10.0.0.10", 22, "user");
try {
await client.authenticateWithPassword("password1");
} catch (error) {
// Try different method
await client.authenticateWithKey(privateKey);
}The legacy API combines connection and authentication in a single call. These methods are deprecated but still supported for backward compatibility.
import SSHClient from '@dylankenneally/react-native-ssh-sftp';
SSHClient.connectWithPassword(
"10.0.0.10",
22,
"user",
"password"
).then(client => {/*...*/});import SSHClient from 'react-native-ssh-sftp';
SSHClient.connectWithKey(
"10.0.0.10",
22,
"user",
privateKey="-----BEGIN RSA...",
passphrase
).then(client => {/*...*/});{privateKey: '-----BEGIN RSA......'}
{privateKey: '-----BEGIN RSA......', publicKey: 'ssh-rsa AAAAB3NzaC1yc2EA......'}
{privateKey: '-----BEGIN RSA......', publicKey: 'ssh-rsa AAAAB3NzaC1yc2EA......', passphrase: 'Password'}
client.disconnect();const command = 'ls -l';
client.execute(command)
.then(output => console.warn(output));- Supported ptyType: vanilla, vt100, vt102, vt220, ansi, xterm
const ptyType = 'vanilla';
client.startShell(ptyType)
.then(() => {/*...*/});client.on('Shell', (event) => {
if (event)
console.warn(event);
});const str = 'ls -l\n';
client.writeToShell(str)
.then(() => {/*...*/});client.closeShell();client.connectSFTP()
.then(() => {/*...*/});const path = '.';
client.sftpLs(path)
.then(response => console.warn(response));client.sftpMkdir('dirName')
.then(() => {/*...*/});client.sftpRename('oldName', 'newName')
.then(() => {/*...*/});client.sftpRmdir('dirName')
.then(() => {/*...*/});client.sftpRm('fileName')
.then(() => {/*...*/});client.sftpDownload('[path-to-remote-file]', '[path-to-local-directory]')
.then(downloadedFilePath => {
console.warn(downloadedFilePath);
});
// Download progress (setup before call)
client.on('DownloadProgress', (event) => {
console.warn(event);
});
// Cancel download
client.sftpCancelDownload();client.sftpUpload('[path-to-local-file]', '[path-to-remote-directory]')
.then(() => {/*...*/});
// Upload progress (setup before call)
client.on('UploadProgress', (event) => {
console.warn(event);
});
// Cancel upload
client.sftpCancelUpload();client.disconnectSFTP();You can find a very simple example app for the usage of this library here.
The example app includes end-to-end (e2e) tests using Detox.
iOS:
- Xcode and iOS Simulator
applesimutils(install viabrew tap wix/brew && brew install applesimutils)
Android:
- Android Studio and Android SDK
- Android emulator with AVD named
Pixel_3a_API_36_ARM
cd example
# Install dependencies
npm install
# iOS
npm run e2e:build:ios
npm run e2e:test:ios
# Android
npm run e2e:build:android
npm run e2e:test:androidCurrent Test Status:
- iOS: ✅ All 18 E2E tests passing with full Detox integration
- Android: ✅ E2E tests working with Android instrumentation testing
- Note: Uses UiAutomator for UI automation instead of Detox
This package wraps the following libraries, which provide the actual SSH/SFTP functionality:
- NMSSH for iOS
- JSch for Android (from Matthias Wiedemann fork)
This package is a fork of Emmanuel Natividad's react-native-ssh-sftp package. The fork chain from there is as follows: